计算点集的最小外接矩形——OpenCV的minAreaRect函数

计算点集的最小外接矩形——OpenCV的minAreaRect函数

函数原型

输入一系列二维点,返回其最小外接矩形。

RotatedRect minAreaRect( InputArray points );

根据函数原型,输入的数据可以是vector<Point>类型,包含1个以上的点;
返回值是RotatedRect类型,该类型的定义如下:

class CV_EXPORTS RotatedRect
{
public:
    //! default constructor
    RotatedRect();
    /** full constructor
    @param center 矩形的质心
    @param size 矩形的宽和高
    @param angle 顺时针定义的旋转角。当值为0, 90, 180, 270等90的整数倍时,该矩形为直立矩形(底边水平)
    */
    RotatedRect(const Point2f& center, const Size2f& size, float angle);
    RotatedRect(const Point2f& point1, const Point2f& point2, const Point2f& point3);

    /** returns 返回矩形的四个顶点
    @param pts 顺序是原始矩形的左下、左上、右上、右下顶点(顺时针顺序)。
    */
    void points(Point2f pts[]) const;
    //! returns 返回当前矩形的最小外接直立矩形(坐标为整数)
    Rect boundingRect() const;
    //! returns 返回包含当前矩形的最小外接矩形(坐标为浮点数),不适合用于图像
    Rect_<float> boundingRect2f() const;
    //! returns 质心
    Point2f center;
    //! returns 宽、高
    Size2f size;
    //! returns 矩形相对于直立矩形的旋转角。
    float angle;
};

对于用户而言,最重要的是三个属性:centersizeangle。其中sizeangle需要着重介绍一下:

RotatedRect的size成员变量

某些用户可能认为宽width<高height,但是size成员变量中,并非如此!宽width表示矩形底边的长度,高height表示矩形竖直边的长度。

void points()输出的点坐标顺序

官方文档定义,points输出的点在原始(未旋转)矩形中依次是左下、左上、右上、右下点,说的有些不明不白;
实际上,序号为0的点是minAreaRect返回的矩形最左侧的点,1\2\3号点依次按顺时针确定。请参照下一节的图示。

RotatedRect的angle成员变量

该变量描述了矩阵从直立旋转到当前状态顺时针转过的角度值,其取值范围是[0,90]
换句话说,angle是points()输出的0号点与1号点构成的线段与竖直方向的夹角。请参照下一节的图示。

矩形顶点编号与角度图示

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

测试代码

给出一段测试代码,方便读者理解该函数:

#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"

#include <iostream>

using namespace cv;
using namespace std;

static void help()
{
    cout << "This program demonstrates finding the minimum enclosing box of a set\n"
        << "of points using function: minAreaRect().\n"
        << "Random points are generated and then enclosed.\n\n"
        << "Press ESC, 'q' or 'Q' to exit and any other key to regenerate the set of points.\n\n";
}

int main(int /*argc*/, char** /*argv*/)
{
    help();

    Mat img(500, 500, CV_8UC3, Scalar::all(0));
    RNG& rng = theRNG();

    for (;;)
    {
        int i, count = rng.uniform(1, 101);
        vector<Point> points;

        // Generate a random set of points
        for (i = 0; i < count; i++)
        {
            Point pt;
            pt.x = rng.uniform(img.cols / 4, img.cols * 3 / 4);
            pt.y = rng.uniform(img.rows / 4, img.rows * 3 / 4);

            points.push_back(pt);
        }

        // Find the minimum area enclosing bounding box
        Point2f vtx[4];
        RotatedRect box = minAreaRect(points);
        box.points(vtx);

        img = Scalar::all(0);

        // Draw the points
        for (i = 0; i < count; i++)
            circle(img, points[i], 3, Scalar(0, 0, 255), FILLED, LINE_AA);
        
        // 定义圆弧的参数
        cv::Point center = vtx[0];
        cv::Size axes(10, 10);
        double angle = 0;
        double startAngle = -90; // 圆弧起始角度(以度为单位)
        double endAngle = box.angle-90; // 圆弧结束角度(以度为单位)
        cv::Scalar color(0, 255, 0); // 绿色

        // 在图像上绘制表示角度的圆弧
        cv::ellipse(img, center, axes, angle, startAngle, endAngle, color,2);
        line(img, vtx[0], cv::Point(vtx[0].x,48), Scalar(255, 255, 255), 1, LINE_AA);
        // Draw the bounding box
        for (i = 0; i < 4; i++)
        {
            line(img, vtx[i], vtx[(i + 1) % 4], Scalar(0, 255, 0), 1, LINE_AA);
            putText(img, to_string(i), vtx[i]-cv::Point2f(16,-32), FONT_HERSHEY_SIMPLEX, 1, Scalar(255, 255, 255));
        }
        // Show the text info about the rectangle box.
        cv::String strRectInfo = "The angle is: ";
        strRectInfo += std::to_string(box.angle);
        cv::putText(img, strRectInfo, cv::Point(0, 32), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(255,255,255));
        imshow("Rectangle, triangle & circle", img);

        char key = (char)waitKey();
        if (key == 27 || key == 'q' || key == 'Q') // 'ESC'
            break;
    }

    return 0;
}

参考

opencv官方文档

相关推荐

  1. OpenCV:绘制图像中mask矩形

    2024-03-16 10:36:01       54 阅读
  2. PCL 球形包围盒

    2024-03-16 10:36:01       25 阅读
  3. NumPynp.dot函数计算积与矩阵乘积利器

    2024-03-16 10:36:01       43 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-16 10:36:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-16 10:36:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-16 10:36:01       82 阅读
  4. Python语言-面向对象

    2024-03-16 10:36:01       91 阅读

热门阅读

  1. XML语言的学习记录2-XMLHttpRequest

    2024-03-16 10:36:01       44 阅读
  2. 如何在 openGauss 中使用 zhparser

    2024-03-16 10:36:01       47 阅读
  3. docker设置容器独立ip(linux下虚拟机设置独立ip)

    2024-03-16 10:36:01       45 阅读
  4. c语言-输入包含空格的字符串

    2024-03-16 10:36:01       37 阅读
  5. Lua-Lua虚拟机2

    2024-03-16 10:36:01       43 阅读
  6. unity 按钮回弹根据新接到的信号设置

    2024-03-16 10:36:01       34 阅读
  7. 从原理总结chatGPT的Prompt的方法

    2024-03-16 10:36:01       46 阅读
  8. Vue开发日志:清空表单数据

    2024-03-16 10:36:01       43 阅读
  9. SSL---VPN

    SSL---VPN

    2024-03-16 10:36:01      39 阅读
  10. 不同情绪调节策略影响拖延行为的神经基础

    2024-03-16 10:36:01       32 阅读