Opencv---RotatedRect

在Robomaster比赛中,RotatedRect类极为常用,灯条、装甲板以至于整车都可以用RotatedRect类来表示。

一、基本概念与用途

RotatedRect 是OpenCV中用于表示旋转矩形的类,常用于需要描述矩形方向(角度)的场景,如:

  • 目标检测中的倾斜边界框(如灯条、装甲板、车牌、文本检测)。
  • 形状分析中的方向感知(如椭圆拟合后的方向)。
  • 几何变换中的旋转矩形表示。

与普通轴对齐矩形 Rect 的区别:

  • Rect 仅包含位置和尺寸(轴对齐)。
  • RotatedRect 包含中心点、尺寸、旋转角度,可表示任意方向的矩形。
二、类定义与构造函数
1. 成员变量(C++)
cpp 复制代码
class RotatedRect {
public:
    Point2f center;   // 中心点坐标(x, y)
    Size2f size;      // 矩形尺寸(宽, 高)
    float angle;      // 旋转角度(单位:度,逆时针为正)
    // 构造函数、成员函数...
};
2. 构造方式
  • 标准构造 :通过中心点、尺寸、角度初始化。

    cpp 复制代码
    // C++
    RotatedRect rRect(Point2f(cx, cy), Size2f(w, h), angle);
    
    // Python
    rRect = cv2.RotatedRect((cx, cy), (w, h), angle)
  • 从轮廓/点集拟合 :通过 minAreaRect() 函数从点集计算最小面积旋转矩形。

    cpp 复制代码
    // C++
    vector<Point2f> points; // 轮廓点集
    RotatedRect rRect = minAreaRect(points);
    
    // Python
    rRect = cv2.minAreaRect(cnt)  # cnt为轮廓点集(numpy数组)
三、核心知识点讲解
1. 旋转角度(angle)的定义
  • 方向 :矩形的水平轴 (长边)与图像坐标系x轴的夹角,逆时针为正
  • 范围约定 :OpenCV中 angle 通常位于 -90° < angle ≤ 0° 。当矩形竖放时(高 > 宽),会自动交换宽高,并将角度调整为 -90° < angle ≤ 0° 。例如:
    • 若原始宽=20,高=40,角度=30°,则实际存储为宽=40,高=20,角度=-60°(保证宽≥高,角度在约定范围)。
2. 顶点坐标计算(points()函数)

通过 RotatedRectpoints() 方法(C++)或 cv2.boxPoints()(Python)获取矩形的4个顶点,顺序为:

  1. 左上角顶点(中心点左侧,沿旋转方向第一个点)。
  2. 右上角顶点(中心点右侧,顺时针第二个点)。
  3. 右下角顶点
  4. 左下角顶点

示例代码

cpp 复制代码
// C++
vector<Point2f> vertices;
rRect.points(vertices); // vertices包含4个顶点,顺序如上述

// Python
vertices = cv2.boxPoints(rRect)  # 返回numpy数组,形状为(4,2)
3. 与轴对齐矩形(Rect)的转换
  • 获取包围旋转矩形的最小轴对齐矩形

    cpp 复制代码
    Rect boundRect = rRect.boundingRect2f(); // C++,返回浮点型Rect
    python 复制代码
    x, y, w, h = cv2.boundingRect(vertices.astype(int))  # Python,需先转换为整数顶点
  • 旋转矩形转普通矩形:仅取顶点坐标的极值,不保留角度信息。

4. 几何运算
  • 面积与周长

    cpp 复制代码
    float area = rRect.size.width * rRect.size.height; // 面积
    float perimeter = 2 * (rRect.size.width + rRect.size.height); // 周长(非旋转周长)
  • 旋转矩阵计算 :以中心点为原点,计算旋转后的坐标变换矩阵:

    cpp 复制代码
    Mat rotationMat = getRotationMatrix2D(rRect.center, rRect.angle, 1.0); // 旋转矩阵
5. 绘制与可视化

通过顶点坐标绘制旋转矩形:

cpp 复制代码
// C++
for (int i = 0; i < 4; i++) {
    line(img, vertices[i], vertices[(i+1)%4], Scalar(0, 255, 0), 2);
}

// Python
for i in range(4):
    cv2.line(img, tuple(vertices[i].astype(int)), tuple(vertices[(i+1)%4].astype(int)), (0, 255, 0), 2)
6. 碰撞检测(两旋转矩形相交判断)

OpenCV未直接提供相交检测函数,需手动实现:

  1. 将旋转矩形转换为多边形(4顶点)。

  2. 使用 分离轴定理(SAT)多边形相交算法 判断是否相交。

  3. 示例思路:

    python 复制代码
    def is_rotated_rect_intersect(r1, r2):
        box1 = cv2.boxPoints(r1).astype(int)
        box2 = cv2.boxPoints(r2).astype(int)
        # 转换为凸多边形,使用cv2.pointPolygonTest判断点是否在另一多边形内
        for p in box1:
            if cv2.pointPolygonTest(box2, tuple(p), False) >= 0:
                return True
        for p in box2:
            if cv2.pointPolygonTest(box1, tuple(p), False) >= 0:
                return True
        return False
四、注意事项与常见误区
  1. 角度与宽高的绑定关系

    • angle(-90°, 0] 时,size.width ≥ size.height(长边为水平轴)。
    • 若手动设置 angle > 0°size.width < size.height,OpenCV会自动调整宽高和角度,以保证约定范围。
  2. 顶点顺序的一致性

    • points() 返回的顶点顺序固定,可通过顺时针或逆时针顺序绘制闭合矩形。
  3. 浮点精度问题

    • 顶点坐标默认为浮点型,绘制时需转换为整数(astype(int)),避免亚像素误差。
  4. 与椭圆(Ellipse)的区别

    • RotatedRect 是矩形,Ellipse 是椭圆,拟合时根据形状选择工具(如 fitEllipse() 返回椭圆,minAreaRect() 返回矩形)。
五、应用场景示例
1. 目标检测中的倾斜边界框
python 复制代码
# 假设检测到轮廓cnt,提取旋转矩形
cnt = ... # 轮廓点集
rRect = cv2.minAreaRect(cnt)
vertices = cv2.boxPoints(rRect).astype(int)
cv2.polylines(img, [vertices], isClosed=True, color=(0, 255, 0), thickness=2)
2. 形状方向分析
cpp 复制代码
// 计算矩形的主方向(角度)
float angle = rRect.angle;
if (angle < -45) angle += 90; // 转换为0°~90°范围的方向角
3. 图像旋转后的边界框调整
python 复制代码
# 对图像旋转θ角后,重新计算旋转矩形的位置
def rotate_image_with_box(img, rRect, theta):
    rows, cols = img.shape[:2]
    M = cv2.getRotationMatrix2D(rRect.center, theta, 1.0)
    rotated_img = cv2.warpAffine(img, M, (cols, rows))
    # 调整旋转矩形的角度
    new_rRect = cv2.RotatedRect(rRect.center, rRect.size, rRect.angle + theta)
    return rotated_img, new_rRect
六、跨语言差异(C++ vs Python)
特性 C++ Python
构造函数参数 Point2f, Size2f, float 元组 (cx, cy), (w, h), float
顶点获取 points(vector<Point2f>&) cv2.boxPoints(rRect) 返回numpy数组
序列化 需手动存储成员变量 可转为元组或JSON存储
七、数学原理补充(顶点坐标推导)

设中心点为 (c_x, c_y),尺寸为 (w, h),角度为 θ,则4个顶点坐标可通过旋转矩阵计算:

  • 原始矩形(未旋转)的顶点相对于中心点的坐标:
    (±w/2, ±h/2)(左上:(-w/2, -h/2),右上:(w/2, -h/2),右下:(w/2, h/2),左下:(-w/2, h/2))。

  • 旋转θ角后的坐标:

    x ′ y ′ \] = \[ cos ⁡ θ − sin ⁡ θ sin ⁡ θ cos ⁡ θ \] \[ x y \] + \[ c x c y \] \\begin{bmatrix} x' \\\\ y' \\end{bmatrix} = \\begin{bmatrix} \\cosθ \& -\\sinθ \\\\ \\sinθ \& \\cosθ \\end{bmatrix} \\begin{bmatrix} x \\\\ y \\end{bmatrix} + \\begin{bmatrix} c_x \\\\ c_y \\end{bmatrix} \[x′y′\]=\[cosθsinθ−sinθcosθ\]\[xy\]+\[cxcy

  • 代入4个顶点的原始坐标,得到旋转后的绝对坐标。


我们太看重了白昼,又太忽视着黑夜。生命,至少有一半是在黑夜中呀。 ---史铁生

相关推荐
庞德公1 小时前
PARSCALE:大语言模型的第三种扩展范式
人工智能·计算机视觉·大模型·并行计算·moe
AI.NET 极客圈1 小时前
AI与.NET技术实操系列(六):实现图像分类模型的部署与调用
人工智能·分类·.net
geneculture1 小时前
《黄帝内经》数学建模与形式化表征方式的重构
人工智能·算法·机器学习·数学建模·重构·课程设计·融智学的重要应用
渝欢意1 小时前
机器学习——逻辑回归
人工智能·机器学习·逻辑回归
EasyDSS2 小时前
EasyRTC嵌入式音视频通信SDK一对一音视频通信,打造远程办公/医疗/教育等场景解决方案
人工智能·音视频
www_pp_2 小时前
# 深入解析BERT自然语言处理框架:原理、结构与应用
人工智能·自然语言处理·bert
jndingxin2 小时前
OpenCV CUDA模块图像过滤------用于创建一个最小值盒式滤波器(Minimum Box Filter)函数createBoxMinFilter()
人工智能·opencv·计算机视觉
Leinwin2 小时前
借助Azure AI Foundry 如何打造语音交互新体验
人工智能·microsoft·azure
缘友一世2 小时前
PyTorch可视化工具——使用Visdom进行深度学习可视化
人工智能·pytorch·深度学习
liuyang-neu2 小时前
目标检测 Sparse DETR(2022)详细解读
人工智能·目标检测·目标跟踪