I’m having troubles with rotation. What I want to do is this:
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
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;
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.
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.