Pergunta

Estou tentando realizar uma inclinação em uma imagem, como uma mostrada aqui


(fonte: Microsoft.com)
.

Eu tenho uma variedade de pixels representando minha imagem e não tenho certeza do que fazer com eles.

Foi útil?

Solução

Uma maneira muito melhor de fazer isso é por Mapeamento inverso.

Essencialmente, você quer "deformar" a imagem, certo? O que significa que todos os pixels da imagem de origem vão para um ponto predefinido - a predefinição é uma matriz de transformação que informa como girar, escalar, traduzir, cisalhamento etc. A imagem que está essencialmente pegando alguma coordenada (x,y) Na sua imagem e dizendo que "ok, a nova posição para este pixel é (f(x),g(y)).

Isso é essencialmente o que "deformação" faz.

Agora, pense em escalar uma imagem ... diga, para dez vezes o tamanho. Então isso significa que o pixel em (1,1) torna -se o pixel em (10,10) - e então o próximo pixel, (1,2) torna -se o pixel (10,20) na nova imagem. Mas se você continuar fazendo isso, você não terá valores para um pixel, (13,13) Porque, (1.3,1.3) não está definido em sua imagem original e você terá um monte de orifícios em sua nova imagem - você terá que interpolar para esse valor usando os quatro pixels ao redor da nova imagem, ou seja, (10,10) , (10,20), (20,10), (200,2) - Isso é chamado Interpolação bilinear.

Mas aqui está outro problema, suponha que sua transformação não tenha sido simples e afine (como a imagem de amostra que você postou)- então (1,1) se tornaria algo como (2.34,4.21) E então você teria que contorná -los na imagem de saída para (2,4) e então Você teria que fazer interpolação bilinear na nova imagem para preencher os buracos ou a interpolação mais complicada - bagunçada, certo?

Agora, há de jeito nenhum Para sair da interpolação, mas podemos se safar de fazer interpolação bilinear, apenas uma vez. Como? Simples, Mapeamento inverso.

Em vez de olhar para ele como a imagem de origem que vai para a nova imagem, pense em onde os dados da nova imagem virão na imagem de origem! Então, (1,1) Na nova imagem virá de algum mapeamento reverso na imagem de origem, digamos, (3.4, 2.1) E então faça a interpolação bilinear na imagem de origem para descobrir o valor correspondente!

Matriz de transformação

Ok, então como você define uma matriz de transformação para uma transformação afim? Esse site diz a você como fazer isso compositando diferentes matrizes de transformação para rotação, cisalhamento, etc.

Transformações:

alt text

Composição:

alt text

A matriz final pode ser alcançada com a composição de cada matriz na ordem e você invertido Para obter o mapeamento inverso - use esta computação as posições dos pixels na imagem de origem e interpolam.

Outras dicas

Se você não tiver vontade de reinventar a roda, consulte a biblioteca OpenCV. Ele implementa muitas funções úteis de processamento de imagens, incluindo transformações em perspectiva. Confira o CVwarpperspective que eu costumava realizar essa tarefa com bastante facilidade.

Como comentado por Kennytm, você só precisa de uma transformação afim que seja um mapeamento linear obtido multiplicando cada pixel por uma matriz M e adicionando o resultado a um vetor de tradução V. É uma matemática simples

end_pixel_position = M*start_pixel_position + V

Onde M é uma composição de transformações simples como rotações ou escalas e V é um vetor que traduz todos os pontos de suas imagens adicionando coeficientes fixos a cada pixel.

Por exemplo, se você deseja girar a imagem, pode ter uma matriz de rotação definida como:

    | cos(a) -sin(a) |
M = |                |
    | sin(a)  cos(a) |

Onde a é o ângulo pelo qual você deseja girar sua imagem.

Enquanto o Scaling usa uma matriz do formulário:

    | s1   0 |
M = |        |
    | 0   s2 |

Onde s1 e s2 são fatores de escala nos dois eixos.

Para tradução, você só tem o vetor V:

    | t1 |
V = |    |
    | t2 |

Isso adiciona t1 e t2 para coordenadas de pixels.

Você então combina as matrizes em uma única transformação, por exemplo, se tiver escala, rotação e tradução, acabará tendo algo como:

| x2 |             | x1 |
|    | = M1 * M2 * |    | + T
| y2 |             | y1 |

Onde:

  • x1 e y1 são coordenadas de pixel antes de aplicar a transformação,
  • x2 e y2 são pixels após a transformação,
  • M1 e M2 são matrizes usadas para escala e rotação (LEMBRAR: A composição das matrizes não é comutativa! Usualmente M1 * M2 * Vect != M2 * M1 * Vect),
  • T é um vetor de tradução usado para traduzir todos os pixels.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top