14

I’m having troubles with rotation. What I want to do is this:

  • Rotate an image
  • Detect features on the rotated image (points)
  • Rotate back the points so I can have the points coordinates corresponding to the initial image

I’m a bit stuck on the third step.

I manage to rotated the image with the following code:

cv::Mat M(2, 3, CV_32FC1);
cv::Point2f center((float)dst_img.rows / 2.0f, (float)dst_img.cols / 2.0f);
M = cv::getRotationMatrix2D(center, rotateAngle, 1.0);
cv::warpAffine(dst_img, rotated, M, cv::Size(rotated.cols, rotated.rows));

I try to rotate back the points with this code:

float xp = r.x * std::cos( PI * (-rotateAngle) / 180 ) - r.y * sin(PI * (rotateAngle) / 180);
float yp = r.x * sin(PI * (-rotateAngle) / 180) + r.y * cos(PI * (rotateAngle) / 180);

It is not to fare to be working but the points don’t go back well on the image. There is an offset.

Thank you for your help

david
  • 502
  • 3
  • 8
  • 17
  • why don't you try to rotate back your matrix with -rotate angle, getRotationMatrix(), and warp affine... – jmartel Jul 28 '11 at 20:38
  • 1
    Why not just use an inverse matrix to the rotation matrix? Trigonometry sounds fragile to me. – Karel Petranek Jul 28 '11 at 20:38
  • Yes but how do I find back the points in the rotated matrix? – david Jul 28 '11 at 21:10
  • Possible duplicate of [C++: Rotating a vector around a certain point](http://stackoverflow.com/questions/620745/c-rotating-a-vector-around-a-certain-point) – dasWesen Oct 19 '16 at 18:31

4 Answers4

8

If M is the rotation matrix you get from cv::getRotationMatrix2D, to rotate a cv::Point p with this matrix you can do this:

cv::Point result;
result.x = M.at<double>(0,0)*p.x + M.at<double>(0,1)*p.y + M.at<double>(0,2);
result.y = M.at<double>(1,0)*p.x + M.at<double>(1,1)*p.y + M.at<double>(1,2);

If you want to rotate a point back, generate the inverse matrix of M or use cv::getRotationMatrix2D(center, -rotateAngle, scale) to generate a matrix for reverse rotation.

Fei
  • 1,187
  • 1
  • 16
  • 35
3

For a rotation matrix, its transpose is its inverse. So you can just do M.t() * r to move it back to your original frame, where r is a cv::Mat (you might have to convert it to a cv::Mat from a cv::Point2f or whatever, or just write out the matrix multiplication explicitly).

Here's the code to do it explicitly (should be correct, but warning, it's entirely untested):

cv::Point2f p;
p.x = M.at<float>(0, 0) * r.x + M.at<float>(1, 0) * r.y;
p.y = M.at<float>(0, 1) * r.x + M.at<float>(1, 1) * r.y;
// p contains r rotated back to the original frame.
Sean
  • 3,002
  • 1
  • 26
  • 32
  • I would like to use your code to do the matrix multiplication explicitly but I'm having a assertion error with the element access. `code`OpenCV Error: Assertion failed (dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && ((((sizeof(size_t)<<28)|0x8442211) >> ((DataType<_Tp>::depth) & ((1 << 3) - 1))*4) & 15) == elemSize1()) in unknown function, file C:\OpenCV2.2\include\opencv2/core/mat.hpp, line 517`code` – david Jul 31 '11 at 22:40
  • you formula misses translation from M – Stepan Yakovenko Aug 17 '18 at 12:57
2

I had the same problem.

For a transform M and point pp in the rotated image, we wish to find the point pp_org in the coordanates of the original image. Use the following lines:

cv::Mat_<double> iM;
cv::invertAffineTransform(M, iM);
cv::Point2f pp_org = iM*pp;

Where the operator * in the above line is defined as:

cv::Point2f operator*(cv::Mat_<double> M, const cv::Point2f& p)
{ 
    cv::Mat_<double> src(3/*rows*/,1 /* cols */); 

    src(0,0)=p.x; 
    src(1,0)=p.y; 
    src(2,0)=1.0; 

    cv::Mat_<double> dst = M*src; //USE MATRIX ALGEBRA 
    return cv::Point2f(dst(0,0),dst(1,0)); 
} 

Note: M is the rotation matrix you used to go from the original to the rotated image

Yonatan Simson
  • 2,395
  • 1
  • 24
  • 35
0
  • You need to rotate your points accorning to center point of your image.
  • Here x and y are your points which you want to rotate, imageCenter_x aand _y is center point of your image.
  • Below is my code.

    angle = angle * (M_PI / 180);  
    float axis_x = x - imageCenter_x;  
    float axis_y = y - imageCenter_y;       
    
    x = axis_x * cos(angle) + axis_y * sin(angle);   
    y = (-axis_x) * sin(angle) + axis_y * cos(angle);
    
    x = x + imageCenter_x;  
    y = y + imageCenter_y;
    
Sagar Patel
  • 864
  • 1
  • 11
  • 22