Image rotation based on OPENCV and C + + underlying implementations

Source: Internet
Author: User
Tags cos pow sin

The rotation of the picture is essentially the position of the original image for each pixel in the rotated picture. And then copy it over.

(In other words, if the position calculated in the original image is not an integer but a decimal, because the number of pixels is an integer, a decimal-to-integer conversion is required.) This conversion process is fastidious and requires interpolation: nearest neighbor interpolation, bilinear interpolation, and so on. Here I am using the simplest nearest neighbor interpolation, that is, rounding up decimals into integers, c/s implementation rounding see here )

The rotation transformation matrix, where T is the angle that needs to be rotated, [x '; y '] is the transformed coordinate (where the semicolon represents the upper and lower relation) is generally introduced in the graphic image class:


is expressed as: [x '; y '] = [cos (t) sin (t);-sin (t) cos (t)][x; y]

Because my personal interests and hobbies (P is the teacher forced ...) ), it is not allowed to use the OpenCV encapsulated rotation function. Can only be self-fulfilling, I started the idea is: the transformation matrix inverse matrix, and then a full black map of each point one by one corresponding interpolation to the original image.

It turns out the picture is completely black after conversion ...

It was later found that the origin was not set. Use the mat format in OpenCV to store (or two-dimensional) a picture of the original point in the upper left corner . But want to implement the rotation origin in the picture center .

at the same time, Span style= "Color:rgb (51,51,51); font-family:arial; line-height:26px; FONT-SIZE:14PX ">mat format store (or two-dimensional array) Y-Axis positive direction down

The most important point is the one that is very easy to ignore in a two-dimensional array operation: Array operation is an array subscript , not a coordinate system (the number of rows in the array rows is the width width of the rectangle , the number of columns Cols is the long length of the rectangle ). such as the coordinate system (in order to be closer to the array layout, we assume that the y-axis coordinate system is downward ), the rectangle vertex is:


In the array, however, because the row takes precedence, the subscript value for four points is:


Have you found that the two coordinates are the opposite!


To summarize, we need to note the following points in the picture rotation:

    1. each pixel (i; j) in the transformed picture needs to be shifted to the new coordinate of the relative rotation center, i.e. (I-MAT.ROWS/2; j-mat.cols/2). Once the calculation is complete, you need to restore the old coordinates to the original point of the upper left corner again;
    2. It is necessary to change the image by multiplying the inverse matrix of the original transformation matrix to the coordinates of the original map. However, because the y-axis direction downward, so the transformed picture multiplied by the original transformation matrix (no inverse matrix) can correspond to the original coordinates (50 degrees clockwise rotation, the restoration operation is counterclockwise rotation 50 degrees);
    3. Before the matrix subscript and the original transformation matrix are multiplied, the matrix subscript two values should be interchanged. After multiplying, the subscript values need to be interchanged again to revert to the matrix subscript.

So for a pixel value that is labeled [m ', N '] after a rotated T-degree, the array subscript [M; n] is reverted to the original image as:

[cos (t)-sin (t); sin (t) cos (t)] ([m '; n ']-[MAT.ROWS/2; MAT.COLS/2]) = [M; n]- [MAT.ROWS/2; MAT.COLS/2]

Source code attached:

Mat nearestneighrotate (cv::mat img, float angle) {int len = (int) (Sqrtf (Pow (img.rows, 2) + POW (img.cols, 2)) + 0.5); Mat Retmat = Mat::zeros (len, Len, cv_8uc3), float Anglepi = angle * Cv_pi/180;int xSm, ysm;for (int i = 0; i < RETMAT.R oWS i++) for (int j = 0; J < Retmat.cols; J + +) {xSm = (int) ((I-RETMAT.ROWS/2) *cos (Anglepi)-(J-RETMAT.COLS/2) *sin (ANGLEPI) + 0.5) ySm = (int) ((I-RETMAT.ROWS/2) *sin (Anglepi) + (J-RETMAT.COLS/2) *cos (ANGLEPI) + 0.5); XSm + = Img.rows/2;ysm + = Img.col S/2;if (xSm >= img.rows | | ySm >= img.cols | | xSm <= 0 | | ySm <= 0) {retmat.at<vec3b> (i, j) = vec3b (0, 0 );} Else{retmat.at<vec3b> (i, j) = Img.at<vec3b> (XSm, ySm);}} return Retmat;}
OK, let's test it out:

int main () {     Mat img = Imread (". /helloworld.png ");    retimg = Nearestneighrotate (img, -20.f);    Namedwindow ("Nearneigh", cv_window_autosize);    Imshow ("Nearneigh", retimg);    Waitkey ();     Cvdestroyallwindows ();    
The result (rotated 20 degrees) is

Image rotation based on OPENCV and C + + underlying implementations

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.