× {{alert.msg}} Never ask again
Get notified about new tutorials RECEIVE NEW TUTORIALS

Can I simply add affine or perspective (homography) matrices of transformation?

Ray Phan
Apr 22, 2015
<p>No, you need to <strong>multiply</strong> the matrices to get the cascaded effect. I won't go into the math, but applying a transformation to coordinates is a matter of performing a matrix multiplication. If you are however curious as to know why that is, I refer you to this <a href="http://en.wikipedia.org/wiki/Transformation_matrix#Composing_and_inverting_transformations" rel="nofollow">good Wikipedia article on cascading matrix transformations</a>. Given a coordinate <code>X</code> and a transformation matrix <code>M</code>, you get the output coordinate <code>Y</code> by:</p> <pre><code>Y = M*X </code></pre> <p>Here I use <code>*</code> to refer to <strong>matrix</strong> multiplication as opposed to element-wise multiplication. What you have is a pair of transformation matrices which go from <code>img1</code> to <code>img2</code> then <code>img2</code> to <code>img3</code>. You'll need to do the operation twice. So to go from <code>img1</code> to <code>img2</code> where <code>X</code> belongs to the coordinate space of <code>img1</code>, we have (assuming we're using the affine matrices):</p> <pre><code>Y1 = M1*X </code></pre> <p>Next, to go from <code>img2</code> to <code>img3</code>, we have:</p> <pre><code>Y2 = M2*Y1 --&gt; Y2 = M2*M1*X --&gt; Y2 = M3*X --&gt; M3 = M2*M1 </code></pre> <p>Therefore, to get the desired chain effect, you need to create a new matrix such that <code>M2</code> is multiplied by <code>M1</code>. Same as <code>H2</code> and <code>H1</code>.</p> <p>So define a new matrix such that:</p> <pre><code>cv::Mat M3 = M2*M1; </code></pre> <p>Similarly for your projective matrices, you can do:</p> <pre><code>cv::Mat H3 = H2*H1; </code></pre> <p>However, <code>estimateRigidTransform</code> (the output is <code>M</code> in your case) gives you a <code>2 x 3</code> matrix. One trick is to augment this matrix so that it becomes 3 x 3 where we add an additional row where it is all 0 <strong>except</strong> for the last element, which is set to 1. Therefore, you would have the last row such that it becomes <code>[0 0 1]</code>. You would do this for both matrices, multiply them, then extract just the first two rows into a new matrix to pipe into <code>warpAffine</code>. Therefore, do something like this:</p> <pre><code>// Create padded matrix for M1 cv::Mat M1new = cv::Mat(3,3,M1.type()); M1new.at&lt;double&gt;(0,0) = M1.at&lt;double&gt;(0,0); M1new.at&lt;double&gt;(0,1) = M1.at&lt;double&gt;(0,1); M1new.at&lt;double&gt;(0,2) = M1.at&lt;double&gt;(0,2); M1new.at&lt;double&gt;(1,0) = M1.at&lt;double&gt;(1,0); M1new.at&lt;double&gt;(1,1) = M1.at&lt;double&gt;(1,1); M1new.at&lt;double&gt;(1,2) = M1.at&lt;double&gt;(1,2); M1new.at&lt;double&gt;(2,0) = 0.0; M1new.at&lt;double&gt;(2,1) = 0.0; M1new.at&lt;double&gt;(2,2) = 1.0; // Create padded matrix for M2 cv::Mat M2new = cv::Mat(3,3,M2.type()); M2new.at&lt;double&gt;(0,0) = M2.at&lt;double&gt;(0,0); M2new.at&lt;double&gt;(0,1) = M2.at&lt;double&gt;(0,1); M2new.at&lt;double&gt;(0,2) = M2.at&lt;double&gt;(0,2); M2new.at&lt;double&gt;(1,0) = M2.at&lt;double&gt;(1,0); M2new.at&lt;double&gt;(1,1) = M2.at&lt;double&gt;(1,1); M2new.at&lt;double&gt;(1,2) = M2.at&lt;double&gt;(1,2); M2new.at&lt;double&gt;(2,0) = 0.0; M2new.at&lt;double&gt;(2,1) = 0.0; M2new.at&lt;double&gt;(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&lt;double&gt;(0,0) = M3temp.at&lt;double&gt;(0,0); M3.at&lt;double&gt;(0,1) = M3temp.at&lt;double&gt;(0,1); M3.at&lt;double&gt;(0,2) = M3temp.at&lt;double&gt;(0,2); M3.at&lt;double&gt;(1,0) = M3temp.at&lt;double&gt;(1,0); M3.at&lt;double&gt;(1,1) = M3temp.at&lt;double&gt;(1,1); M3.at&lt;double&gt;(1,2) = M3temp.at&lt;double&gt;(1,2); </code></pre> <p>When dealing with <code>cv::Mat</code> and the <code>*</code> operator, <a href="http://docs.opencv.org/modules/core/doc/basic_structures.html#matrix-expressions" rel="nofollow">it is overloaded to specifically perform matrix multiplication</a>.</p> <p>You can then use <code>M3</code> and <code>H3</code> into <code>warpAffine</code> and <code>warpPerspective</code> respectively.</p> <hr> <p>Hope this helps!</p> <p>This tip was originally posted on <a href="http://stackoverflow.com/questions/29749344/Can%20I%20simply%20add%20affine%20or%20perspective%20(homography)%20matrices%20of%20transformation?/29759351">Stack Overflow</a>.</p>
comments powered by Disqus