Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rotating back points from a rotated image in OpenCV

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

like image 955
david Avatar asked Jul 28 '11 20:07

david


2 Answers

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

like image 56
Yonatan Simson Avatar answered Sep 19 '22 21:09

Yonatan Simson


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.

like image 39
Fei Avatar answered Sep 21 '22 21:09

Fei