Opencv Rect、RotatedRect类中的成员详解
Rect类:
Rect类为直立矩形,顾名思义,即两条边与图像坐标系平行。
类中有成员:
成员变量 | 成员函数 |
---|---|
x(左上角点的坐标) | Size()返回值为Size |
y(左上角点的坐标) | area()返回矩形的面积 |
width(矩形宽) | contain(Point)判断点是否在该矩形内 |
height(矩形高) | inside()判断矩形是否在该矩形内 |
-------- | tl()返回左上角点坐标 |
-------- | br()返回右下角点坐标 |
还可进行如下操作:
RoateRect类:
在OpenCV中,经常要用到minAreaRect()函数求最小外接矩形(旋转矩形)。通常用来存储最小外包矩形函数minAreaRect( )和椭圆拟合函数fitEllipse( )返回的结果。该函数返回一个RotatedRect类对象。
RotatedRect类定义如下:
class CV_EXPORTS RotatedRect
{
public:
//! various constructors
RotatedRect();
RotatedRect(const Point2f& center, const Size2f& size, float angle);
RotatedRect(const CvBox2D& box);
//! returns 4 vertices of the rectangle
void points(Point2f pts[]) const;
//! returns the minimal up-right rectangle containing the rotated rectangle
Rect boundingRect() const;
//! conversion to the old-style CvBox2D structure
operator CvBox2D() const;
Point2f center; //< the rectangle mass center
Size2f size; //< width and height of the rectangle
float angle; //< the rotation angle. When the angle is 0, 90, 180, 270 etc., the rectangle becomes an up-right rectangle.
};
类中有成员:
成员变量 | 成员函数 |
---|---|
center(中心点) | points()函数求矩形的四个顶点 |
size(尺寸,包括width、height) | boundingrect()函数求最小外接矩形,与坐标轴平行(或垂直)的最小矩形 |
angle(角度) |
其中旋转矩形角度理解如下:minAreaRect()返回的旋转矩形,旋转角度angle的范围为[-90,0),当矩形水平或竖直时均返回-90。
图片来源:https://blog.csdn.net/qq_24237837/article/details/77850496
角度如何产生?哪条边为宽?哪条边为高?
下面给出解释:
也就是说,opencv的原点在左上角,横向为x轴,纵向为y轴,将x轴逆时针转动,碰到的第一条边(延长线)就为宽(width),另一条边就为高(height),而与之所成角度就为angle。如下图:
自己可以做细些小程序测验一下,画出各个位置矩形框输出角度,角度确实已经确定了,但是width“有问题”,当我们算宽高比时,若不加判断,有些情况下(宽>高的实际情况)就会出错(结果相反),那如何解决呢?
我是首先判断:width/height <1?,若是,则需要交换width和height 的值,这样在后续操作才不会出错。
if ((rect.size.width / rect.size.height) < 1)
rect.angle = 90 + rect.angle;//正数,逆时针旋转
else
rect.angle = rect.angle; //负数,顺时针旋转
这时就以水平轴为界,向上为正角度,向下为负角度。
当然你也可以进行其他角度转换定义,说白了就是数学公式转换而已。
fitEllipse()返回的旋转矩形角度为:
角度参数angle 是椭圆中心center发出的平行于x轴的射线,顺时针旋转,与椭圆短轴的夹角,取值范围 [ 0 ~ 180 ]。
椭圆的短轴为参数size里面的第一个参数width,长轴为参数size里面的第二个参数height。
旋转矩形的四个顶点points()顺序为下图所示:
相必看图就很明白了四个点的顺序,因为我所研究对象为竖直灯条(可以左右偏离一定角度),所以用下面的代码对其进行排序以便后面使用,你也可以根据自己需要作出定义。
Point2f points[4];
rect.points(points);
Point2f lu, ld, ru, rd;
if (switchangle(rect) < 0)//这里的switchangle()就是上面转换角度的定义函数
{
lu = points[2];
ld = points[1];
ru = points[3];
rd = points[0];
}
else {
lu = points[1];
ld = points[0];
ru = points[2];
rd = points[3];
}