opencv求最小外接矩阵

求最小外接矩阵的基本原理:

获取点簇最开始的minx,maxx,miny,maxy确定最初的外接矩形,求外接矩形的面积,然后对点簇进行旋转,按照下面公式即可:

旋转之后,求出新的minx,maxx,miny,maxy,计算此时的面积,直到面积达到最小,对应的即为最小外接矩形。

关于图像旋转参考:https://blog.csdn.net/zhouxuguang236/article/details/31820095

1.输入是一幅图,如边缘图(如canny边缘检测后,仅有0与255)

       测试代码:

        vector<vector<Point>> contours;
        vector<Vec4i> hierarchy;
        findContours(edge, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());
        Mat imageContours = Mat::zeros(edge.size(), CV_8UC1);
        int idx, maxcontours = 0;
        vector<Point> selectpoint;
        for (int i = 0; i < contours.size(); i++)//有可能识别出几组点簇分布,取出最大的点簇
        {
            vector<Point> ptmp = contours[i];
            if (ptmp.size() > maxcontours)
            {
                selectpoint = ptmp;
                idx = i;
            }
        }

        //绘制轮廓
        drawContours(imageContours, contours, idx, Scalar(255), 1, 8, hierarchy);

        //绘制轮廓的最小外接矩形
        RotatedRect rect = minAreaRect(selectpoint);
        Point2f P[4];
        rect.points(P);//外接矩形的四个顶点
        for (int j = 0; j <= 3; j++)
        {
            line(imageContours, P[j], P[(j + 1) % 4], Scalar(255), 2);
        }
        imshow("MinAreaRect", imageContours);
        waitKey(0);

注意:

(1)部分关键量解释

contours;//向量内每个元素保存了一组由连续的Point点构成的点的集合的向量,每一组Point点集就是一个轮廓。
                   //有多少轮廓,向量contours就有多少元素
hierarchy;//向量内每一个元素包含了4个int型变量,向量hiararchy内的元素和轮廓向量contours内的元素是一一对应的,向量的容量相同。每一个元素的4个int型变量——hierarchy[i][0] ~hierarchy[i][3],分别表示第i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。如果当前轮廓没有对应的后一个轮廓、前一个轮廓、父轮廓或内嵌轮廓的话,则hierarchy[i][0] ~hierarchy[i][3]的相应位被设置为默认值-1。

findContours(edge, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());
//RETR_EXTERNAL,只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略。
//CHAIN_APPROX_NONE,保存物体边界上所有连续的轮廓点到contours向量中。

(2)可能出现的问题

一般情况下,我们都期望找到包括图像所有边缘的最小外接矩阵,但这种方法可能产生问题。如输入图像如下图:

其会分成两组点簇:蓝圈部分与红圈部分。

取最大的点簇可能取不完整我们需要的矩形边界,但可能外接矩阵没问题,如下图。但是点簇右下边缺失,不利于后续操作,所以不推荐使用这种方法。

   

2.输入是一组点(x,y)

测试代码:

        vector<Point> pointxy;
        vector<vector<Point>> aglcontours0;
        find_edge_coordinate(edge,pointxy);//提取边缘部分,将图像中边缘部分的点提取出来,并保存
        aglcontours0.push_back(pointxy);
        Mat imageContours = Mat::zeros(edge.size(), CV_8UC1);
        drawContours(imageContours, aglcontours0, 0, Scalar(255), 1, 8);

        RotatedRect rect = minAreaRect(pointxy);//查找最小外接矩形
        Point2f P[4];
        rect.points(P);//外接矩形的四个顶点
        for (int j = 0; j <= 3; j++)
        {
            line(imageContours, P[j], P[(j + 1) % 4], Scalar(128), 2);
        }
        imshow("MinAreaRect", imageContours);
        waitKey(0);

输出显示:

说明:不知道为啥中间部分也成了白色的。。。。。。

猜你喜欢

转载自blog.csdn.net/u013925378/article/details/83866448