该篇博客是记录并分享使用C++ opencv绘制旋转矩形,该代码可以实时显示旋转的过程。
首先贴出效果图:
蓝色—原始矩形
绿色—旋转矩形
白色—旋转矩形的外接矩形
下面是代码:
// opencv_study.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
using namespace cv;
using namespace std;
vector<Point>middle_point; //定义一个vector用于储存弧线的坐标
void draw_rectangle(Mat* draw_img, Point center_xy, Size wh, float angle)
{
int write_angle = abs(angle);
angle = angle * CV_PI / 180; //转换成pi
//获取原始矩形左上、右上、右下、左下的坐标
Point point_L_U = Point(center_xy.x - wh.width / 2, center_xy.y - wh.height / 2); //左上
Point point_R_U = Point(center_xy.x + wh.width / 2, center_xy.y - wh.height / 2); //右上
Point point_R_L = Point(center_xy.x + wh.width / 2, center_xy.y + wh.height / 2); //右下
Point point_L_L = Point(center_xy.x - wh.width / 2, center_xy.y + wh.height / 2); //左下
Point point[4] = { point_L_U,point_R_U,point_R_L,point_L_L }; //原始矩形数组
Point after_point[4] = { Point(0,0) }; //旋转后的矩形数组
for (int i = 0; i < 4; i++) //求旋转后的对应坐标
{
int x = point[i].x - center_xy.x;
int y = point[i].y - center_xy.y;
after_point[i].x = cvRound( x * cos(angle) + y * sin(angle) + center_xy.x);
after_point[i].y = cvRound(-x * sin(angle) + y * cos(angle) + center_xy.y);
}
for (int j = 0; j < 3; j++) //绘制旋转后的矩形 红色
{
line(*draw_img, after_point[j], after_point[j + 1], Scalar(0, 255, 0));
if (j == 2)
{
line(*draw_img, after_point[j + 1], after_point[0], Scalar(0, 255, 0));
}
}
line(*draw_img, center_xy, after_point[1], Scalar(0, 255, 0)); //绘制一条中点到左上角的线
Point end_point = Point(cvRound((after_point[1].x + center_xy.x) / 2),
cvRound((after_point[1].y + center_xy.y) / 2)); //弧线结束点坐标,中点到右上角的1/2
middle_point.push_back(end_point);
for (int i = 0; i < middle_point.size()-1; i++) //绘制弧线
{
line(*draw_img, middle_point[i], middle_point[i+1], Scalar(0, 255, 0));
}
Point font_point = Point((middle_point[middle_point.size() / 2].x + 2 * center_xy.x) / 3,
(middle_point[middle_point.size() / 2].y + 2 * center_xy.y) / 3 ); //用于显示角度字符的位置
string text = to_string(write_angle);
putText(*draw_img, text, font_point, cv::FONT_HERSHEY_COMPLEX, 0.5, Scalar(0, 255, 0), 1); //显示字符在图像上
}
int main()
{
Point center_xy = Point(200, 200); //定义矩形的中心点坐标与长宽
Size wh = Size(150, 100);
float angle = 120.; //负为顺时针,正为逆时针
Point start_point = Point(cvRound((center_xy.x + wh.width / 2 + center_xy.x) / 2),
cvRound((center_xy.y - wh.height / 2 + center_xy.y) / 2)); //绘制用于显示旋转角度的弧线的开始点坐标,中心点到右上角的1/2
middle_point.push_back(start_point);
for (int i = 0; abs(i) < abs(int(angle))+1;) //循环动态显示矩形旋转过程
{
Mat img = Mat::zeros(Size(400, 400), CV_8UC3); //生成一张图片
RotatedRect *r_R = new RotatedRect(center_xy, wh, i); //生成旋转矩形
draw_rectangle(&img, center_xy, wh, i); //绘制旋转矩形
Rect r = r_R->boundingRect(); //求旋转矩形的外接矩形
rectangle(img, r, Scalar(255, 255, 255)); //绘制外接矩形 白色
Rect org_r = Rect(center_xy.x - wh.width / 2, center_xy.y - wh.height / 2, wh.width, wh.height); //求原始矩形参数
rectangle(img, org_r, Scalar(255, 0, 0)); //绘制原始矩形 蓝色
line(img, center_xy, Point(center_xy.x + wh.width / 2, center_xy.y - wh.height / 2),Scalar(255,0,0)); //绘制原始矩形中点到右上角的直线
delete r_R;
imshow("Rect", img);
waitKey(20);
if (angle < 0) { --i; }
if (angle >= 0) { ++i; }
}
waitKey();
return 0;
}
有个问题需要说明下,代码中求旋转矩形的公式是在网上找的,如下:
int x = point[i].x - center_xy.x;
int y = point[i].y - center_xy.y;
after_point[i].x = cvRound( x * cos(angle) + y * sin(angle) + center_xy.x);
after_point[i].y = cvRound(-x * sin(angle) + y * cos(angle) + center_xy.y);
这个公式和我自己推导出来的不一样,但是测试结果显示是正确的,所以还是有点疑惑,欢迎各位朋友指正。公式推导可以参考这个博客。