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

46 篇文章 0 订阅
本文详细解释了OpenCV中的minAreaRect函数,用于计算二维点集的最小外接矩形,并介绍了RotatedRect类的结构,特别是center、size和angle属性。通过测试代码演示了如何使用这个函数并展示其输出结果。
摘要由CSDN通过智能技术生成

计算点集的最小外接矩形——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官方文档

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
OpenCV中,可以使用函数`minAreaRect()`来求取一些点集最小外接矩形。具体步骤如下: 1. 将点集转换为`cv::Mat`类型。 2. 调用`minAreaRect()`函数,传入点集的`cv::Mat`类型参数。 3. 函数返回一个`RotatedRect`类型的对象,表示最小外接矩形。 下面是一个示例代码: ```c++ #include <opencv2/opencv.hpp> int main() { // 定义点集 std::vector<cv::Point2f> points = { cv::Point2f(100, 100), cv::Point2f(200, 200), cv::Point2f(150, 300), cv::Point2f(50, 250) }; // 将点集转换为cv::Mat类型 cv::Mat pointMat(points); // 求取最小外接矩形 cv::RotatedRect rect = cv::minAreaRect(pointMat); // 可以通过调用rect函数来获取最小外接矩形的信息 cv::Point2f rectPoints[4]; rect.points(rectPoints); // 绘制最小外接矩形点集 cv::Mat image = cv::Mat::zeros(500, 500, CV_8UC3); for (int i = 0; i < points.size(); i++) { cv::circle(image, points[i], 3, cv::Scalar(0, 255, 0), -1); } for (int i = 0; i < 4; i++) { cv::line(image, rectPoints[i], rectPoints[(i + 1) % 4], cv::Scalar(0, 0, 255), 2); } cv::imshow("Minimum bounding box", image); cv::waitKey(0); return 0; } ``` 在上面的代码中,我们首先定义了一个点集,然后将其转换为`cv::Mat`类型,并调用`minAreaRect()`函数求取最小外接矩形。最后,我们绘制了最小外接矩形点集,效果如下图所示: ![最小外接矩形示例](https://img-blog.csdn.net/20170621135442100?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTM2NzQ1NQ==/font/5a6L5L2T/fontsize/400)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值