Prévia do material em texto
Transformações geométricas em coordenadas homogêneas 2-D Coordenadas homogêneas (ou coordenadas projetivas, abreviado CHs) são um sistema de co- ordenadas usada na geometria projetiva. Um ponto em R 2 (x,y) é representado em CHs utilizando 3 números (x,y,w). O ponto em CHs (x,y,w) representa o ponto (x/w, y/w) em R 2 . Por exemplo, (4,6,2) em CHs representa o ponto (2,3) de R 2 . Se w=1, dizemos que a repre- sentação está normalizada. Exemplo da representação em CHs normalizada: (2,3,1). Figura retirada de Wikipedia. Matriz 2x2 (transformação linear): Representando os pontos por vetores 2x1, a transformação entre pontos é representada por uma matriz 2x2. Matriz 2x2 consegue representar rotação (em torno do centro do sistema de coordenadas), “shearing”, reflexão e mudança de escala. Exemplos: Rotação: v v n n y x cs sc y x , c=cos() e s=sin() Shearing: v v n n y xk y x 10 1 Reflexão em torno do eixo X: v v n n y x y x 10 01 Mudança de escala: v v y x n n y x e e y x 0 0 Uma composição de transformações pode ser obtida multiplicando as matrizes de transforma- ção. A transformação inversa é calculada pela inversa da matriz. x y Matriz 2x3 (transformação afim): Se utilizar matrizes de transformação 2x3, consegue representar transformações afins. Elas incluem (além das transformações 2x2) a translação. Consegue mapear retângulo em parale- lograma (mantém o paralelismo das retas). Translação por (tx, ty): 1 10 01 v v y x n n y x t t y x A função “getAffineTransform” consegue determinar a matriz de transformação 2x3 a partir de 3 pares de pontos correspondentes. O problema de transformação 2x3 é que não dá para multiplicar duas matrizes 2x3, assim co- mo não existe matriz inversa de uma matriz 2x3. Exemplo: //shear.cpp pos2016 #include <cekeikon.h> int main() { Mat_<FLT> src = (Mat_<FLT>(3,2) << 0,0, 0,511, 511,511); cout << src << endl; Mat_<FLT> dst = (Mat_<FLT>(3,2) << 200,100, 100,400, 400,400); cout << dst << endl; Mat_<FLT> m=getAffineTransform(src,dst); cout << m << endl; Mat_<GRY> a; le(a,"lenna.jpg"); Mat_<GRY> b; warpAffine(a,b,m,a.size(),INTER_LINEAR,BORDER_WRAP); imp(b,"afim.png"); } [0.58708417, -0.19569471, 200; 0, 0.58708417, 100] O seguinte programa faz rotação em torno de um ponto arbitrário: #include <cekeikon.h> int main() { Mat_<GRY> ent; le(ent,"c:/haepi/imagens/comum/lennag.tga"); Mat_<GRY> sai; Mat_<double> m=getRotationMatrix2D(Point2f(ent.cols/2,ent.rows/2), 30, 1); cout << m << endl; warpAffine(ent, sai, m, ent.size(), INTER_LINEAR, BORDER_CONSTANT, Scalar(255)); mostra(sai); } Saída: [0.8660254037844387, 0.4999999999999999, -93.70250336881629; -0.4999999999999999, 0.8660254037844387, 162.2974966311837] Como construir a matriz m manualmente, sem usar a função getRotationMatrix2D? Utilizan- do matrizes 3x3. dx=256; dy=256; (T(dx,dy) * R(30) * T(-dx,-dy)) * (xv, yv, 1)t //manual.cpp #include <cekeikon.h> Mat_<double> translacao(double tx, double ty) { Mat_<double> m(3,3, 0.0); m(0,0)=1; m(1,1)=1; m(2,2)=1; m(0,2)=tx; m(1,2)=ty; return m; } Mat_<double> rotacao(double graus) { double radianos=deg2rad(graus); double co=cos(radianos); double se=sin(radianos); Mat_<double> m(3,3, 0.0); m(0,0)=co; m(0,1)=se; m(1,0)=-se; m(1,1)=co; m(2,2)=1; return m; } int main() { Mat_<double> m=translacao(256,256)*rotacao(30)*translacao(-256,-256); cout << m << endl; } Saída: [0.8660254037844387, 0.4999999999999999, -93.70250336881628; -0.4999999999999999, 0.8660254037844387, 162.2974966311837; 0, 0, 1] Despreza-se a última linha. Matriz 3x3 (transformação perspectiva): Usando sistema de coordenadas homogêneas (matriz 3x3) permitem efetuar rotação, transla- ção, reflexão, mudança de escala, transformação afim e transformação em perspectiva. A composição das transformações é calculada pela multiplicação matricial. A transformação in- versa é dada pela inversa da matriz. Rotação em coordenadas homogêneas: 1100 0 0 1 v v n n y x cs sc y x RA, onde c=cos(A) e s=sin(A) Translação em coordenadas homogêneas: 1100 10 01 1 v v y x n n y x t t y x Tt, onde t = (tx, ty). Mudança de escala em coordenadas homogêneas: 1100 00 00 1 v v y x n n y x e e y x Ee, onde e = (ex, ey). As matrizes podem ser multiplicadas para obter transformação composta. Por exemplo, rota- ção de A graus em torno de centro c = (cx, cy): T-c · RA · Tc . O seguinte programa corrige o efeito em perspectiva (usando rotinas de OpenCV): pv warppers quadrado1.bmp quadrado1b.pgm 55 156 585 156 0 324 639 324 10 156 630 156 10 324 630 324 pv warppers quadrado2.bmp quadrado2b.pgm 237 156 639 205 0 260 451 324 10 10 630 10 10 470 630 470 pv warppers ka0.jpg ka1.jpg 73 0 533 0 -22 479 626 479 10 10 630 10 10 470 630 470 quadrado1.bmp quadrado1b.pgm quadrado2.bmp quadrado2b.pgm ka0.jpg ka1.jpg //pers.cpp grad-2017 #include <cekeikon.h> int main() { Mat_<FLT> src = (Mat_<FLT>(4,2) << 70,0, 533,0, -22,479, 626,479); Mat_<FLT> dst = (Mat_<FLT>(4,2) << 10,0, 630,0, 10,479, 630,479); Mat_<FLT> m=getPerspectiveTransform(src,dst); cout << m << endl; Mat_<FLT> v=(Mat_<FLT>(3,1) << 70,0,1); Mat_<FLT> w=m*v; cout << w << endl; Mat_<COR> a; le(a,"ka0.jpg"); Mat_<COR> b; warpPerspective(a,b,m,a.size()); imp(b,"ka1.jpg"); } C:\haepi\algpi\transgeom\grad2017>persp [1.3390929, 0.26553699, -83.736504; 1.373901e-015, 1.3995681, -5.6843419e-013; 6.3154777e-018, 0.00083417125, 1] [9.9999924; -4.7226112e-013; 1] É possível usar mais de 4 pontos para achar a transformação em perspectiva. Fica mais robus- to. Mat findHomography(InputArray srcPoints, InputArray dstPoints, int me- thod=0, double ransacReprojThreshold=3, OutputArray mask=noArray() ) method – Method used to computed a homography matrix. The following methods are possible: – 0 - a regular method using all the points – CV_RANSAC - RANSAC-based robust method – CV_LMEDS - Least-Median robust method Veja o manual do OpenCV. Escrever sobre calibração de câmera. Escrever sobre correçãode defeito da lente.