Home | History | Annotate | Download | only in warp_affine
      1 Affine Transformations {#tutorial_warp_affine}
      2 ======================
      3 
      4 Goal
      5 ----
      6 
      7 In 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 
     12 Theory
     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 
     80 Code
     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 
     95 Explanation
     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 
    189 Result
    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