1Affine Transformations {#tutorial_warp_affine} 2====================== 3 4Goal 5---- 6 7In this tutorial you will learn how to: 8 9- Use the OpenCV function @ref cv::warpAffine to implement simple remapping routines. 10- Use the OpenCV function @ref cv::getRotationMatrix2D to obtain a \f$2 \times 3\f$ rotation matrix 11 12Theory 13------ 14 15### What is an Affine Transformation? 16 17-# It is any transformation that can be expressed in the form of a *matrix multiplication* (linear 18 transformation) followed by a *vector addition* (translation). 19-# From the above, We can use an Affine Transformation to express: 20 21 -# Rotations (linear transformation) 22 -# Translations (vector addition) 23 -# Scale operations (linear transformation) 24 25 you can see that, in essence, an Affine Transformation represents a **relation** between two 26 images. 27 28-# The usual way to represent an Affine Transform is by using a \f$2 \times 3\f$ matrix. 29 30 \f[ 31 A = \begin{bmatrix} 32 a_{00} & a_{01} \\ 33 a_{10} & a_{11} 34 \end{bmatrix}_{2 \times 2} 35 B = \begin{bmatrix} 36 b_{00} \\ 37 b_{10} 38 \end{bmatrix}_{2 \times 1} 39 \f] 40 \f[ 41 M = \begin{bmatrix} 42 A & B 43 \end{bmatrix} 44 = 45 \begin{bmatrix} 46 a_{00} & a_{01} & b_{00} \\ 47 a_{10} & a_{11} & b_{10} 48 \end{bmatrix}_{2 \times 3} 49 \f] 50 51 Considering that we want to transform a 2D vector \f$X = \begin{bmatrix}x \\ y\end{bmatrix}\f$ by 52 using \f$A\f$ and \f$B\f$, we can do it equivalently with: 53 54 \f$T = A \cdot \begin{bmatrix}x \\ y\end{bmatrix} + B\f$ or \f$T = M \cdot [x, y, 1]^{T}\f$ 55 56 \f[T = \begin{bmatrix} 57 a_{00}x + a_{01}y + b_{00} \\ 58 a_{10}x + a_{11}y + b_{10} 59 \end{bmatrix}\f] 60 61### How do we get an Affine Transformation? 62 63-# Excellent question. We mentioned that an Affine Transformation is basically a **relation** 64 between two images. The information about this relation can come, roughly, in two ways: 65 -# We know both \f$X\f$ and T and we also know that they are related. Then our job is to find \f$M\f$ 66 -# We know \f$M\f$ and \f$X\f$. To obtain \f$T\f$ we only need to apply \f$T = M \cdot X\f$. Our information 67 for \f$M\f$ may be explicit (i.e. have the 2-by-3 matrix) or it can come as a geometric relation 68 between points. 69 70-# Let's explain a little bit better (b). Since \f$M\f$ relates 02 images, we can analyze the simplest 71 case in which it relates three points in both images. Look at the figure below: 72 73 ![](images/Warp_Affine_Tutorial_Theory_0.jpg) 74 75 the points 1, 2 and 3 (forming a triangle in image 1) are mapped into image 2, still forming a 76 triangle, but now they have changed notoriously. If we find the Affine Transformation with these 77 3 points (you can choose them as you like), then we can apply this found relation to the whole 78 pixels in the image. 79 80Code 81---- 82 83-# **What does this program do?** 84 - Loads an image 85 - Applies an Affine Transform to the image. This Transform is obtained from the relation 86 between three points. We use the function @ref cv::warpAffine for that purpose. 87 - Applies a Rotation to the image after being transformed. This rotation is with respect to 88 the image center 89 - Waits until the user exits the program 90 91-# The tutorial code's is shown lines below. You can also download it from 92 [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp) 93 @include samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp 94 95Explanation 96----------- 97 98-# Declare some variables we will use, such as the matrices to store our results and 2 arrays of 99 points to store the 2D points that define our Affine Transform. 100 @code{.cpp} 101 Point2f srcTri[3]; 102 Point2f dstTri[3]; 103 104 Mat rot_mat( 2, 3, CV_32FC1 ); 105 Mat warp_mat( 2, 3, CV_32FC1 ); 106 Mat src, warp_dst, warp_rotate_dst; 107 @endcode 108-# Load an image: 109 @code{.cpp} 110 src = imread( argv[1], 1 ); 111 @endcode 112-# Initialize the destination image as having the same size and type as the source: 113 @code{.cpp} 114 warp_dst = Mat::zeros( src.rows, src.cols, src.type() ); 115 @endcode 116-# **Affine Transform:** As we explained lines above, we need two sets of 3 points to derive the 117 affine transform relation. Take a look: 118 @code{.cpp} 119 srcTri[0] = Point2f( 0,0 ); 120 srcTri[1] = Point2f( src.cols - 1, 0 ); 121 srcTri[2] = Point2f( 0, src.rows - 1 ); 122 123 dstTri[0] = Point2f( src.cols*0.0, src.rows*0.33 ); 124 dstTri[1] = Point2f( src.cols*0.85, src.rows*0.25 ); 125 dstTri[2] = Point2f( src.cols*0.15, src.rows*0.7 ); 126 @endcode 127 You may want to draw the points to make a better idea of how they change. Their locations are 128 approximately the same as the ones depicted in the example figure (in the Theory section). You 129 may note that the size and orientation of the triangle defined by the 3 points change. 130 131-# Armed with both sets of points, we calculate the Affine Transform by using OpenCV function @ref 132 cv::getAffineTransform : 133 @code{.cpp} 134 warp_mat = getAffineTransform( srcTri, dstTri ); 135 @endcode 136 We get as an output a \f$2 \times 3\f$ matrix (in this case **warp_mat**) 137 138-# We apply the Affine Transform just found to the src image 139 @code{.cpp} 140 warpAffine( src, warp_dst, warp_mat, warp_dst.size() ); 141 @endcode 142 with the following arguments: 143 144 - **src**: Input image 145 - **warp_dst**: Output image 146 - **warp_mat**: Affine transform 147 - **warp_dst.size()**: The desired size of the output image 148 149 We just got our first transformed image! We will display it in one bit. Before that, we also 150 want to rotate it... 151 152-# **Rotate:** To rotate an image, we need to know two things: 153 154 -# The center with respect to which the image will rotate 155 -# The angle to be rotated. In OpenCV a positive angle is counter-clockwise 156 -# *Optional:* A scale factor 157 158 We define these parameters with the following snippet: 159 @code{.cpp} 160 Point center = Point( warp_dst.cols/2, warp_dst.rows/2 ); 161 double angle = -50.0; 162 double scale = 0.6; 163 @endcode 164-# We generate the rotation matrix with the OpenCV function @ref cv::getRotationMatrix2D , which 165 returns a \f$2 \times 3\f$ matrix (in this case *rot_mat*) 166 @code{.cpp} 167 rot_mat = getRotationMatrix2D( center, angle, scale ); 168 @endcode 169-# We now apply the found rotation to the output of our previous Transformation. 170 @code{.cpp} 171 warpAffine( warp_dst, warp_rotate_dst, rot_mat, warp_dst.size() ); 172 @endcode 173-# Finally, we display our results in two windows plus the original image for good measure: 174 @code{.cpp} 175 namedWindow( source_window, WINDOW_AUTOSIZE ); 176 imshow( source_window, src ); 177 178 namedWindow( warp_window, WINDOW_AUTOSIZE ); 179 imshow( warp_window, warp_dst ); 180 181 namedWindow( warp_rotate_window, WINDOW_AUTOSIZE ); 182 imshow( warp_rotate_window, warp_rotate_dst ); 183 @endcode 184-# We just have to wait until the user exits the program 185 @code{.cpp} 186 waitKey(0); 187 @endcode 188 189Result 190------ 191 192-# After compiling the code above, we can give it the path of an image as argument. For instance, 193 for a picture like: 194 195 ![](images/Warp_Affine_Tutorial_Original_Image.jpg) 196 197 after applying the first Affine Transform we obtain: 198 199 ![](images/Warp_Affine_Tutorial_Result_Warp.jpg) 200 201 and finally, after applying a negative rotation (remember negative means clockwise) and a scale 202 factor, we get: 203 204 ![](images/Warp_Affine_Tutorial_Result_Warp_Rotate.jpg) 205