转载、参考、引用请注明出处。
文章地址:https://blog.csdn.net/duiwangxiaomi/article/details/92565308?spm=1001.2014.3001.5501
minAreaRect()函数计算并返回指定点集的最小区域边界斜矩形。
RotatedRect minAreaRect(InputArray points)
points:输入信息,可以为包含点的容器(vector)或是Mat。RotatedRect :返回一个轮廓的外接矩形,是一个RotatedRect的类。包覆输入信息的最小斜矩形,是一个Box2D结构rect:(最小外接矩形的中心(x,y),(宽度,高度),旋转角度)。
但是要绘制这个矩形,我们需要矩形的4个顶点坐标box, 通过函数 cv2.cv.BoxPoints() 获得,返回形式[ [x0,y0], [x1,y1], [x2,y2], [x3,y3] ]。得到的最小外接矩形的4个顶点顺序、中心坐标、宽度、高度、旋转角度(是度数形式,不是弧度数)的对应关系如下:注意:
- 旋转角度θ是水平轴(x轴)逆时针旋转,与碰到的矩形的第一条边的夹角。并且这个边的边长是width,另一条边边长是height。也就是说,在这里,width与height不是按照长短来定义的。
- 在opencv中,坐标系原点在左上角,相对于x轴,逆时针旋转角度为负,顺时针旋转角度为正。所以,θ∈(-90度,0]。
下面介绍一下矩形顶点的求解方法:
函数:cvBoxPoints(CvBox2D box, CvPoint2D32f pt[4])输入:box 矩形数据,minAreaRect返回的RotatedRect 类就是一个Box2D结构的矩形。
pt 返回的顶点数组。
对应的opencv源码:
void RotatedRect::points(Point2f pt[]) const
{
double _angle = angle*CV_PI/180.;
float b = (float)cos(_angle)*0.5f;
float a = (float)sin(_angle)*0.5f;
pt[0].x = center.x - a*size.height - b*size.width;
pt[0].y = center.y + b*size.height - a*size.width;
pt[1].x = center.x + a*size.height - b*size.width;
pt[1].y = center.y - b*size.height - a*size.width;
pt[2].x = 2*center.x - pt[0].x;
pt[2].y = 2*center.y - pt[0].y;
pt[3].x = 2*center.x - pt[1].x;
pt[3].y = 2*center.y - pt[1].y;
}
CV_IMPL void cvBoxPoints( CvBox2D box, CvPoint2D32f pt[4] )
{
if( !pt )
CV_Error( CV_StsNullPtr, "NULL vertex array pointer" );
cv::RotatedRect(box).points((cv::Point2f*)pt);
}
矩形顶点计算原理:
根据上述图片,推导顶点公式如下:
与源码中公式一致。
参考博客: [1](https://blog.csdn.net/u013925378/article/details/84563011) [2](http://www.pianshen.com/article/4885281921/)