【OpenCV3图像处理】提取轮廓的凸包、外包矩形、最小外包矩形、最小外包圆

版权声明:本文为博主原创文章,欢迎转载,请注明出处 https://blog.csdn.net/u011574296/article/details/73302426

1、提取轮廓的凸包

convexhull()函数(点我看OpenCV3.2帮助文档

这里写图片描述

函数调用形式:

void convexhul(InputArray points,OutputArray hull,bool clockwise=false,bool returnPoints=true)

输入:
第一个参数是要求凸包的点集
第二个参数是输出的凸包点,可以为vector,此时返回的是凸包点在原轮廓点集中的索引,也可以为vector,此时存放的是凸包点的位置
第三个参数是一个bool变量,表示求得的凸包是顺时针方向还是逆时针方向,true是顺时针方向。
第四个参数,第二个参数的返回类型是vector还是vector,可以忽略

示例:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>  
#include<vector>  
#include<opencv2/opencv.hpp>  

using namespace cv;
using namespace std;

int main()
{
    Mat srcImage(Size(500, 500), CV_8UC3, Scalar(0));

    // 随机类RNG,默认的构造函数初始化为固定的值,随机“种子”也是固定的,还有一个带参数的构造函数,你可以指定“种子”,
    // 用系统时间来指定,以确保每次执行都是“不同的种子” 从而得到不同的随机序列
    RNG rng((unsigned)time(NULL));  

    char key;
    while (1)
    {
        //随机生成一些点  
        //首先就是随机生成点的总数量
        int g_nPointCount = rng.uniform(10, 30);
        //接下来就是随机生成一些点的坐标  
        vector<Point> points;
        for (int i = 0; i < g_nPointCount; i++)
        {
            Point midPoint;

            midPoint.x = rng.uniform(srcImage.cols / 4, srcImage.cols * 3 / 4);
            midPoint.y = rng.uniform(srcImage.rows / 4, srcImage.rows * 3 / 4);

            points.push_back(midPoint);
        }

        //显示刚刚随机生成的那些点 
        for (int i = 0; i < g_nPointCount; i++)
        {
            circle(srcImage, points[i], 0, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 3);
        }

        //计算凸包 
        vector<int> hull;
        convexHull(Mat(points), hull, true);
        //绘制凸包
        int hullcount = (int)hull.size();
        Point pt0 = points[hull[hullcount - 1]];
        for (int i = 0;i < hullcount;i++)
        {
            Point pt = points[hull[i]];
            line(srcImage, pt0, pt, Scalar(0, 255, 0), 1, LINE_AA);
            pt0 = pt;
        }

        imshow("效果图", srcImage);

        key = waitKey();
        if (key == 27)
            break;
        else
            srcImage = Scalar::all(0);
    }

    return 0;
}

效果:

这里写图片描述

2、提取轮廓的外包矩形

boundingRect()函数(点我看OpenCV3.2帮助文档

这里写图片描述

函数作用:

计算轮廓的外包矩形,矩形是与图像上下边界平行的

函数调用形式:

Rect boundingRect(InputArray points)

输入:二维点集,点的序列或向量 (Mat)
返回:Rect

示例:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>  
#include<vector>  
#include<opencv2/opencv.hpp>  

using namespace cv;
using namespace std;

int main()
{
    Mat srcImage(Size(500, 500), CV_8UC3, Scalar(0));

    // 随机类RNG,默认的构造函数初始化为固定的值,随机“种子”也是固定的,还有一个带参数的构造函数,你可以指定“种子”,
    // 用系统时间来指定,以确保每次执行都是“不同的种子” 从而得到不同的随机序列
    RNG rng((unsigned)time(NULL));  

    char key;
    while (1)
    {
        //随机生成一些点  
        //首先就是随机生成点的总数量
        int g_nPointCount = rng.uniform(10, 30);
        //接下来就是随机生成一些点的坐标  
        vector<Point> points;
        for (int i = 0; i < g_nPointCount; i++)
        {
            Point midPoint;

            midPoint.x = rng.uniform(srcImage.cols / 4, srcImage.cols * 3 / 4);
            midPoint.y = rng.uniform(srcImage.rows / 4, srcImage.rows * 3 / 4);

            points.push_back(midPoint);
        }

        //显示刚刚随机生成的那些点 
        for (int i = 0; i < g_nPointCount; i++)
        {
            circle(srcImage, points[i], 0, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 3);
        }
        //寻找外包矩阵
        Rect maxRect = boundingRect(points);
        //绘制外包矩阵
        rectangle(srcImage, maxRect, Scalar(0, 255, 0));

        imshow("效果图", srcImage);

        key = waitKey();
        if (key == 27)
            break;
        else
            srcImage = Scalar::all(0);
    }

    return 0;
}

效果图:

这里写图片描述

3、提取轮廓的最小外包矩形

minAreaRect()函数(点我看OpenCV3帮助文档

这里写图片描述

函数作用:

主要求得包含点集最小面积的矩形,这个矩形是可以有偏转角度的,可以与图像的边界不平行

函数调用形式:

RotatedRect minAreaRect(InputArray points)

输入:二维点集,点的序列或向量 (Mat)
返回:RotatedRect

示例:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>  
#include<vector>  
#include<opencv2/opencv.hpp>  

using namespace cv;
using namespace std;

int main()
{
    Mat srcImage(Size(500, 500), CV_8UC3, Scalar(0));

    // 随机类RNG,默认的构造函数初始化为固定的值,随机“种子”也是固定的,还有一个带参数的构造函数,你可以指定“种子”,
    // 用系统时间来指定,以确保每次执行都是“不同的种子” 从而得到不同的随机序列
    RNG rng((unsigned)time(NULL));  

    char key;
    while (1)
    {
        //随机生成一些点  
        //首先就是随机生成点的总数量
        int g_nPointCount = rng.uniform(10, 30);
        //接下来就是随机生成一些点的坐标  
        vector<Point> points;
        for (int i = 0; i < g_nPointCount; i++)
        {
            Point midPoint;

            midPoint.x = rng.uniform(srcImage.cols / 4, srcImage.cols * 3 / 4);
            midPoint.y = rng.uniform(srcImage.rows / 4, srcImage.rows * 3 / 4);

            points.push_back(midPoint);
        }

        //显示刚刚随机生成的那些点 
        for (int i = 0; i < g_nPointCount; i++)
        {
            circle(srcImage, points[i], 0, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 3);
        }

        //寻找最小外包矩形
        RotatedRect minRect = minAreaRect(points);

        Point2f fourPoint2f[4];
        //将minRect的四个顶点坐标值放到fourPoint的数组中  
        minRect.points(fourPoint2f);

        //根据得到的四个点的坐标  绘制矩形  
        for (int i = 0; i < 3; i++)
        {
            line(srcImage, fourPoint2f[i], fourPoint2f[i + 1], Scalar(0,0,255), 3);
        }
        line(srcImage, fourPoint2f[0], fourPoint2f[3], Scalar(0, 0, 255), 3);

        imshow("效果图", srcImage);

        key = waitKey();
        if (key == 27)
            break;
        else
            srcImage = Scalar::all(0);
    }

    return 0;
}

效果图:

这里写图片描述

RotatedRect类的详解,参见我另一篇博客:【opencv3学习笔记】RotatedRect类 详解

4、提取轮廓的最小外包圆

minEnclosingcircle()(点我看OpenCV3帮助文档
这里写图片描述

函数调用形式:

void minEnclosingcircle(InputArray points,Point2f& center,float& radius)

输入:二维点集,点的序列vector< point >或向量 (Mat) ,圆心坐标,半径

示例:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>  
#include<vector>  
#include<opencv2/opencv.hpp>  

using namespace cv;
using namespace std;

int main()
{
    Mat srcImage(Size(500, 500), CV_8UC3, Scalar(0));

    // 随机类RNG,默认的构造函数初始化为固定的值,随机“种子”也是固定的,还有一个带参数的构造函数,你可以指定“种子”,
    // 用系统时间来指定,以确保每次执行都是“不同的种子” 从而得到不同的随机序列
    RNG rng((unsigned)time(NULL));  

    char key;
    while (1)
    {
        //随机生成一些点  
        //首先就是随机生成点的总数量
        int g_nPointCount = rng.uniform(10, 30);
        //接下来就是随机生成一些点的坐标  
        vector<Point> points;
        for (int i = 0; i < g_nPointCount; i++)
        {
            Point midPoint;

            midPoint.x = rng.uniform(srcImage.cols / 4, srcImage.cols * 3 / 4);
            midPoint.y = rng.uniform(srcImage.rows / 4, srcImage.rows * 3 / 4);

            points.push_back(midPoint);
        }

        //显示刚刚随机生成的那些点 
        for (int i = 0; i < g_nPointCount; i++)
        {
            circle(srcImage, points[i], 0, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 3);
        }


        //在生成的那些随机点中寻找最小包围圆形  
        Point2f center; //圆心
        float radius; //半径
        minEnclosingCircle(points, center, radius);

        //根据得到的圆形和半径  绘制圆形  
        circle(srcImage, static_cast<Point>(center), (int)radius, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 3);

        imshow("效果图", srcImage);

        key = waitKey();
        if (key == 27)
            break;
        else
            srcImage = Scalar::all(0);
    }

    return 0;
}

效果图:

这里写图片描述

没有更多推荐了,返回首页