1. 程式人生 > >opencv使用筆記——獲取rotatedRect的內部區域mask

opencv使用筆記——獲取rotatedRect的內部區域mask

原創文章,未經作者允許,請勿轉載,謝謝!

一開始想的是傳統的水漫法,但是想著矩形這麼規則,應該可以有別的方法,於是想到了下面這種小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;
}