问题
I have an image, and I place a rectangle on the image. Then I rotate the image. How do I get the center of the rectangle on the rotated image?
Or can I rotate a rectangle somehow to put on rotated image? I think in this case rotation must be done along same point with point used to rotate image.
This is the image with a rectangle placed on it.
This is the rotated image.
Here is the code I use to rotate my image:
cv::Mat frame, frameRotated;
frame = cv::imread("lena.png");
cv::Rect rect(225,250,150,150);
cv::rectangle(frame, rect, cv::Scalar(0,0,255),2);
int theta = 30;
double radians = theta * PI / 180.0;
double sin = abs(std::sin(radians));
double cos = abs(std::cos(radians));
int newWidth = (int) (frame.cols * cos + frame.rows * sin);
int newHeight = (int) (frame.cols * sin + frame.rows * cos);
cv::Mat targetMat(cv::Size(newWidth, newHeight), frame.type());
int offsetX = (newWidth - frame.cols) / 2;
int offsetY = (newHeight - frame.rows) / 2;
frame.copyTo(targetMat.rowRange(offsetY, offsetY + frame.rows).colRange(offsetX, offsetX + frame.cols));
cv::Point2f src_center(targetMat.cols/2.0F, targetMat.rows/2.0F);
cv::Mat rot_mat = cv::getRotationMatrix2D(src_center, theta, 1.0);
cv::warpAffine(targetMat, frameRotated, rot_mat, targetMat.size());
imshow("frame", frame);
imshow("rotated frame", frameRotated);
EDIT
Suppose I have a point in the rotated image, how do I get corresponding point in the original image using rotation matrix?
回答1:
You only need to use rot_mat to transform the original center of the rect. I tested the below and it works:
cv::Rect r(250, 350, 20, 30);
cv::Point2d c(r.x + r.width / 2, r.y + r.height / 2);
// c is center of rect
// get c's location in targetMat when frame is copied
c.x += offsetX;
c.y += offsetY;
int theta = 30;
double radians = theta * M_PI / 180.0;
cv::Point2d src_center(targetMat.cols/2.0F, targetMat.rows/2.0F);
cv::Mat rot_mat = cv::getRotationMatrix2D(src_center, theta, 1.0);
// now transform point using rot_mat
double *x = rot_mat.ptr<double>(0);
double *y = rot_mat.ptr<double>(1);
Point2d dst(x[0] * c.x + x[1] * c.y + x[2],
y[0] * c.x + y[1] * c.y + y[2]);
// dst is center of transformed rect
EDIT
To transform a point from the rotated image you just need to reverse the process:
// undo translation
Point2d dst1(dst.x - x[2], dst.y - y[2]);
// undo rotation
Point2d dst2(x[0] * dst1.x - x[1] * dst1.y, -y[0] * dst1.x + y[1] * dst1.y);
// undo shift
Point2d in_unrotated_image(dst2.x - offsetX, dst2.y - offsetY);
回答2:
You can translate any point in your source Mat to rotated Mat by multiplying with the Rotation matrix.
If you need to translate X,Y and given T=1, you can do this by Mat multiplication
| cosθ sinθ Tx | | X | | _X |
| | * | Y | = | |
| -sinθ cosθ Ty | | 1 | | _Y |
where Tx and Ty is the translation along the x and y see OpenCV Doc.
Suppose you need to find the centre (cent_x,cent_y) of source Mat in rotated Mat
Mat rot_mat = getRotationMatrix2D(src_center, theta, 1.0); //Find the rotation matrix
Mat co_Ordinate = (Mat_<double>(3,1) << cent_x,cent_y,1); //Create 3x1 matrix with input co-ordinates.
Mat rst=rot_mat*co_Ordinate; // Multiply rotation matrix with input co-ordinate matrix
trans_x=(int)rst.at<double>(0,0); //First row of result will be x
trans_y=(int)rst.at<double>(1,0); //Second row of result will be y.
Hopes these helpful....
回答3:
I've solved the problem in second question.
I used the same code provided in the accepted answer and create rotation matrix with minus theta.
来源:https://stackoverflow.com/questions/19786333/center-of-rotated-cvrect