opencv使用筆記——獲取rotatedRect的內部區域mask
阿新 • • 發佈:2019-01-07
原創文章,未經作者允許,請勿轉載,謝謝!
一開始想的是傳統的水漫法,但是想著矩形這麼規則,應該可以有別的方法,於是想到了下面這種小trick。
1.首先計算rotatedRect的四個頂點。
RotatedRect rRect(Point2f(100, 100), Size2f(100, 50), 30);
Point2f vertices[4]; //定義矩形的4個頂點
rRect.points(vertices); //計算矩形的4個頂點
2,然後根據旋轉角度和中點位置計算旋轉矩陣
cv::Mat rot_mat = cv::getRotationMatrix2D(Point2f(100, 100), 30, 1.0);
3.然後將頂點乘以旋轉矩陣,進行旋轉變換,用於生成一個規則的水平矩形Rect,然後就方便填充了
Mat background = Mat::zeros(back.size(), CV_8UC1); for (int i = 0; i < 4; i++){ Mat point_mat = (Mat_<double>(3, 1) << vertices[i].x, vertices[i].y, 1.0); Mat point_rot = rot_mat * point_mat; Point2f p(point_rot.ptr<double>(0)[0], point_rot.ptr<double>(1)[0]); pp.push_back(p); } Rect rrr = boundingRect(pp); background(rrr) = 255;
4.最後再根據旋轉矩陣,將矩形框仿射變換回去就行了。
rot_mat = cv::getRotationMatrix2D(Point2f(100, 100), -30, 1.0);
cv::warpAffine(background, background, rot_mat, Size2f(200, 200));
img.copyTo(back, background);
完整程式碼如下:
#include <opencv2/opencv.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> using namespace std; using namespace cv; int main() { Mat img = Mat(200,200,CV_8UC3,Scalar(255,255,255)); Mat back = Mat(200, 200, CV_8UC3, Scalar(0, 0, 0)); Mat background = Mat::zeros(back.size(), CV_8UC1); RotatedRect rRect(Point2f(100, 100), Size2f(100, 50), 30); Point2f vertices[4]; //定義矩形的4個頂點 Point2d vertices_d[4]; rRect.points(vertices); //計算矩形的4個頂點 //Rect brect = rRect.boundingRect2f(); //back(brect) = 255; //ellipse(back, rRect, cv::Scalar(0, 255, 255), 2, 8); for (int i = 0; i < 4; i++){ line(back, vertices[i], vertices[(i + 1) % 4], Scalar(0, 255, 0)); } cv::Mat rot_mat = cv::getRotationMatrix2D(Point2f(100, 100), 30, 1.0); cout << rot_mat<<endl; vector<Point2f> pp; //根據旋轉矩陣進行仿射變換 imshow("1", back); Mat dst; cv::warpAffine(back, dst, rot_mat, Size2f(200, 200)); imshow("2",dst); for (int i = 0; i < 4; i++){ Mat point_mat = (Mat_<double>(3, 1) << vertices[i].x, vertices[i].y, 1.0); cout << point_mat <<endl; Mat point_rot = rot_mat * point_mat; cout << point_rot << endl; Point2f p(point_rot.ptr<double>(0)[0], point_rot.ptr<double>(1)[0]); circle(dst, p, 2, Scalar(0, 255, 0)); pp.push_back(p); } Rect rrr = boundingRect(pp); background(rrr) = 255; imshow("3", background); rot_mat = cv::getRotationMatrix2D(Point2f(100, 100), -30, 1.0); Mat temp1; cv::warpAffine(background, background, rot_mat, Size2f(200, 200)); img.copyTo(back, background); imshow("4", back); waitKey(0); return 0; }