2015-04-20 9 views
6

Jak wiadomo, w OpenCV można uzyskać przekształcenie afiniczne lub perspektywicznym od 2 obrazów:Czy mogę po prostu dodać matryce afiniczne lub perspektywiczne (homograficzne) transformacji?

Wtedy mogę zrobić:

  • pokrewieństwa transformację - za pomocą warpAffine(img_src, img_dst, M)
  • perspektywiczny transformację - za pomocą warpPerspective(img_src, img_dst, H)

Ale jeśli mam 3 lub więcej obrazów, a ja już znalazłem:

  • afino: M1 (img1 -> img2), M2 (img2 -> img3)
  • perspektywa: H1 (img1 -> i Mg2), H2 (img2 -> img3)

wtedy mogę dostać Matix transformacji (img1 -> img3), po prostu dodaj dwie matrycę?

  • z afinicznym transform: M3 = M1 + M2;
  • z perspektywy transform: H3 = H1 + H2;

lub które z funkcji należy użyć do tego?

Odpowiedz

4

Nie, musisz pomnożyć macierzy, aby uzyskać efekt kaskadowy. Nie wchodzę w matematykę, ale zastosowanie przekształcenia do współrzędnych jest kwestią wykonywania mnożenia macierzy. Jeśli jednak jesteś ciekawy, dlaczego tak się dzieje, odsyłam Cię do tego good Wikipedia article on cascading matrix transformations. Biorąc pod uwagę koordynować X i macierzą transformacji M, masz wyjście koordynować Y przez:

Y = M*X 

Tutaj używam * odnieść się do mnożenia macierzy w przeciwieństwie do elementu mnożenie. To, co masz, to para macierzy transformacji, które przechodzą od img1 do img2, następnie img2 do img3. Musisz wykonać tę operację dwukrotnie.Tak więc, aby przejść od img1 do img2 gdzie X należący do przestrzeni współrzędnych img1 mamy (zakładając, że używamy macierze afiniczne):

Y1 = M1*X 

Następny, aby przejść od img2 do img3, mamy:

Y2 = M2*Y1 --> Y2 = M2*M1*X --> Y2 = M3*X --> M3 = M2*M1 

Dlatego, aby uzyskać pożądany efekt łańcucha, trzeba utworzyć nową matrycę tak, że M2 jest mnożona przez M1. To samo, co H2 i H1.

więc zdefiniować nową matrycę takie, że:

cv::Mat M3 = M2*M1; 

Podobnie dla rzutowych macierzy, można zrobić:

cv::Mat H3 = H2*H1; 

Jednak estimateRigidTransform (wyjście jest M w danym przypadku) daje macierz 2 x 3. Jedna sztuczka polega na rozszerzeniu tej macierzy tak, aby stała się 3 x 3, gdzie dodajemy dodatkowy wiersz, gdzie wszystko jest 0 , z wyjątkiem dla ostatniego elementu, który jest ustawiony na 1. Dlatego też ostatni wiersz będzie taki, że staje się [0 0 1]. Zrobilibyśmy to dla obu macierzy, pomnożylibyśmy je, a następnie wyodrębniliśmy tylko pierwsze dwa wiersze do nowej macierzy, aby utworzyć rurę w warpAffine. Dlatego też zrobić coś takiego:

// Create padded matrix for M1 
cv::Mat M1new = cv::Mat(3,3,M1.type()); 
M1new.at<double>(0,0) = M1.at<double>(0,0); 
M1new.at<double>(0,1) = M1.at<double>(0,1); 
M1new.at<double>(0,2) = M1.at<double>(0,2); 

M1new.at<double>(1,0) = M1.at<double>(1,0); 
M1new.at<double>(1,1) = M1.at<double>(1,1); 
M1new.at<double>(1,2) = M1.at<double>(1,2); 

M1new.at<double>(2,0) = 0.0; 
M1new.at<double>(2,1) = 0.0; 
M1new.at<double>(2,2) = 1.0; 

// Create padded matrix for M2 
cv::Mat M2new = cv::Mat(3,3,M2.type()); 
M2new.at<double>(0,0) = M2.at<double>(0,0); 
M2new.at<double>(0,1) = M2.at<double>(0,1); 
M2new.at<double>(0,2) = M2.at<double>(0,2); 

M2new.at<double>(1,0) = M2.at<double>(1,0); 
M2new.at<double>(1,1) = M2.at<double>(1,1); 
M2new.at<double>(1,2) = M2.at<double>(1,2); 

M2new.at<double>(2,0) = 0.0; 
M2new.at<double>(2,1) = 0.0; 
M2new.at<double>(2,2) = 1.0; 

// Multiply the two matrices together 
cv::Mat M3temp = M2new*M1new; 

// Extract out relevant rows and place into M3 
cv::Mat M3 = cv::Mat(2, 3, M3temp.type()); 
M3.at<double>(0,0) = M3temp.at<double>(0,0); 
M3.at<double>(0,1) = M3temp.at<double>(0,1); 
M3.at<double>(0,2) = M3temp.at<double>(0,2); 

M3.at<double>(1,0) = M3temp.at<double>(1,0); 
M3.at<double>(1,1) = M3temp.at<double>(1,1); 
M3.at<double>(1,2) = M3temp.at<double>(1,2); 

Gdy mamy do czynienia z cv::Mat a operatorem *, it is overloaded to specifically perform matrix multiplication.

Można następnie użyć odpowiednio M3 i H3 do warpAffine i warpPerspective.


Mam nadzieję, że to pomoże!

+0

Dziękuję bardzo! Ale mnożenie macierzy może być wykonane tylko wtedy, gdy liczba kolumn w 1-st macierzy jest równa liczbie rzędów w 2-macie macierzy. ** H - perspektywa (homografia) to macierz 3x3 ** i ** mogę zrobić: 'H3 = H1 * H2;' **. Ale ** matryca afiniczna to 2x3 ** i nie mogę po prostu pomnożyć dwóch matematycznych afiliacji, ** nie mogę tego zrobić: 'M3 = M1 * M2;' **. Jak mogę to zrobić w Affine Transformation - M? – Alex

+0

'estimateRigidTransform();' daje mi macierz 2x3, 'i estimateAffine3D();' daje mi macierz 3x4. – Alex

+0

@Alex - Dodałem informacje, które pomogą ci w 'estimateRigidTransform'. Przepraszam, że nie widziałem tego wcześniej. Jednak "estimateAffine3D" zajmuje się transformacją między chmurami punktów 3D na inne. Nie można tego użyć do zniekształcania obrazów, ponieważ obrazy są z natury przestrzenią współrzędnych 2D. – rayryeng

Powiązane problemy