2015-04-20 33 views
6

Được biết, trong OpenCV tôi có thể nhận affine hoặc góc độ chuyển đổi giữa 2 hình ảnh:Tôi có thể đơn giản thêm ma trận hoặc ma trận (homography) ma trận chuyển đổi không?

Sau đó, tôi có thể làm:

  • affine chuyển đổi - bằng cách sử dụng warpAffine(img_src, img_dst, M)
  • góc độ chuyển đổi - bằng cách sử dụng warpPerspective(img_src, img_dst, H)

Nhưng nếu tôi có 3 hoặc nhiều hình ảnh, và tôi đã tìm thấy:

  • affine: M1 (img1 -> img2), M2 (img2 -> img3)
  • phối cảnh: H1 (img1 -> i MG2), H2 (img2 -> img3)

sau đó tôi có thể nhận được matix chuyển đổi (img1 -> img3) bằng cách đơn giản thêm hai ma trận?

  • của một affine transform: M3 = M1 + M2;
  • của một góc độ chuyển đổi: H3 = H1 + H2;

Hoặc mà các chức năng tôi nên sử dụng cho việc này?

Trả lời

4

Không, bạn cần phải nhân ma trận để có được hiệu ứng xếp tầng. Tôi sẽ không đi vào toán học, nhưng việc áp dụng một phép biến đổi cho các tọa độ là vấn đề thực hiện phép nhân ma trận. Tuy nhiên, nếu bạn tò mò muốn biết lý do tại sao, tôi giới thiệu bạn đến số good Wikipedia article on cascading matrix transformations này. Cho một phối hợp X và một ma trận chuyển đổi M, bạn sẽ có được sản lượng phối hợp Y bởi:

Y = M*X 

Ở đây tôi sử dụng * để chỉ ma trận nhân như trái ngược với nhân tố khôn ngoan. Những gì bạn có là một cặp ma trận chuyển đổi từ img1 đến img2 rồi img2 đến img3. Bạn sẽ cần thực hiện thao tác này hai lần.Vì vậy, để đi từ img1 để img2 nơi X thuộc về không gian toạ độ img1, chúng tôi đã (giả sử chúng ta đang sử dụng các ma trận affine):

Y1 = M1*X 

Tiếp theo, để đi từ img2 để img3, ta có:

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

Do đó, để có được hiệu ứng chuỗi mong muốn, bạn cần tạo một ma trận mới sao cho M2 được nhân với M1. Tương tự như H2H1.

Vì vậy, xác định một ma trận mới như rằng:

cv::Mat M3 = M2*M1; 

Tương tự như vậy đối với ma trận projective, bạn có thể làm:

cv::Mat H3 = H2*H1; 

Tuy nhiên, estimateRigidTransform (đầu ra là M trong trường hợp của bạn) mang đến cho bạn ma trận 2 x 3. Một mẹo là tăng thêm ma trận này sao cho nó trở thành 3 x 3, trong đó chúng ta thêm một hàng bổ sung khi nó là tất cả 0 trừ cho phần tử cuối cùng, được đặt thành 1. Vì vậy, bạn sẽ có hàng cuối cùng sao cho nó trở thành [0 0 1]. Bạn sẽ làm điều này cho cả hai ma trận, nhân chúng, sau đó trích xuất chỉ hai hàng đầu tiên vào một ma trận mới để đường ống vào warpAffine. Vì vậy, làm một cái gì đó như thế này:

// 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); 

Khi giao dịch với cv::Mat* điều hành, it is overloaded to specifically perform matrix multiplication.

Sau đó, bạn có thể sử dụng M3H3 thành warpAffinewarpPerspective tương ứng.


Hy vọng điều này sẽ hữu ích!

+0

Cảm ơn bạn rất nhiều! Nhưng phép nhân ma trận có thể được thực hiện chỉ khi số cột trong ma trận 1-st bằng với số hàng trong ma trận 2-nd. ** H - phối cảnh (homography) là một ma trận 3x3 **, và ** Tôi có thể làm: 'H3 = H1 * H2;' **. Nhưng ** ma trận affine là một 2x3 ** và tôi không thể đơn giản nhân hai ma trận affine, ** Tôi không thể làm: 'M3 = M1 * M2;' **. Làm thế nào tôi có thể làm điều này cho việc chuyển đổi Affine - M? – Alex

+0

'EstimatedRigidTransform();' cung cấp cho tôi ma trận 2x3, 'và estimatedAffine3D();' cung cấp cho tôi ma trận 3x4. – Alex

+0

@Alex - Tôi đã thêm thông tin để giúp bạn với 'EstimatedRigidTransform'. Tôi xin lỗi vì đã không nhìn thấy điều đó sớm hơn. Tuy nhiên, 'EstimatedAffine3D' giao dịch với sự chuyển đổi giữa một đám mây điểm 3D sang đám mây khác. Bạn không thể sử dụng hình ảnh đó để làm cong hình ảnh vì hình ảnh vốn là không gian tọa độ 2D. – rayryeng

Các vấn đề liên quan