寻找轮廓findContours()、寻找凸包convexHull()、绘制轮廓drawContours() OpenCV

参考网址: findContours函数参数详解

1. 寻找轮廓:findContours函数

(1)原型:

findContours( InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point()); 

参数讲解:

  • 第一个参数:image。
    • 输入图像,填Mat类对象即可,且需为8位单通道图像。
    • 可以是灰度图,更常用的是二值图像。
    • 一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像;
  • 第二个参数:contours。
    • 定义为vector<vector<Point>> contours
    • 是一个向量,并且是一个双重向量。向量内每个元素保存了一组由连续的Point点构成的点的集合的向量,每一组Point点集就是一个轮廓。
    • 有多少轮廓,向量contours就有多少元素。
  • 第三个参数:hierarchy。
    • 定义为vector<Vec4i> hierarchy
    • Vec4i的定义:typedef Vec<int, 4> Vec4i;
      Vec4i是Vec<int,4>的别名。所以从定义上看,hierarchy也是一个向量,向量内每个元素保存了一个包含4个int整型的数组。
    • hierarchy向量包含轮廓之间的拓扑信息。每个轮廓contours[i]对应4个hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分别表示第 i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。如果没有对应项,对应的hierarchy[i]值设置为负数,默认值-1。
  • 第四个参数:int型的mode,定义轮廓的检索模式:
    这里写图片描述

  • 第五个参数:int型的method,定义轮廓的近似方法:
    这里写图片描述

  • 第六个参数:Point偏移量,每个轮廓点相对于原始图像对应点的偏移量。

    • 相当于在每一个检测出的轮廓点上加上该偏移量
    • 默认值为Point()
    • Point可以是负值。

(2)参考代码:

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std; 
using namespace cv;  

int main(int argc,char *argv[])  
{
    Mat imageSource=imread(argv[1],0);
    imshow("Source Image",imageSource);

    Mat image;
    GaussianBlur(imageSource,image,Size(3,3),0);
    Canny(image,image,100,250);

    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    findContours(image,contours,hierarchy,RETR_TREE,CHAIN_APPROX_SIMPLE,Point());

    Mat imageContours=Mat::zeros(image.size(),CV_8UC1);
    Mat Contours=Mat::zeros(image.size(),CV_8UC1);  //绘制
    for(int i=0;i<contours.size();i++)
    {
        //contours[i]代表的是第i个轮廓,contours[i].size()代表的是第i个轮廓上所有的像素点数
        for(int j=0;j<contours[i].size();j++) 
        {
            //绘制出contours向量内所有的像素点
            Point P=Point(contours[i][j].x,contours[i][j].y);
            Contours.at<uchar>(P)=255;
        }

        //输出hierarchy向量内容
        char ch[256];
        sprintf(ch,"%d",i);
        string str=ch;
        cout<<"向量hierarchy的第" <<str<<" 个元素内容为:"<<endl<<hierarchy[i]<<endl<<endl;

        //绘制轮廓
        drawContours(imageContours,contours,i,Scalar(255),1,8,hierarchy);
    }
    imshow("Contours Image",imageContours); //轮廓
    imshow("Point of Contours",Contours);   //向量contours内保存的所有轮廓点集
    waitKey(0);
    return 0;
}

2. 寻找凸包:convexHull()函数

(1)函数原型:

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

参数就是之前计算出的轮廓和用于输出的集合。可以参见《OpenCV3编程入门》第313页。

(2)参考代码(找出最外尾轮廓,并寻找凸包,绘制轮廓与凸包):

#include <iostream>
#include <opencv2/opencv.hpp>    

using namespace std;

int main()
{

    Mat inImg = imread("F:/test_photo/luanphoto10.png", 0);
    imshow("input image", inImg);

    Mat inImgTemp = inImg.clone();

    GaussianBlur(inImgTemp, inImgTemp, Size(3, 3), 0);
    Canny(inImgTemp, inImgTemp, 100, 250);

    vector<vector<Point>> contours;
    findContours(inImgTemp, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point());

    Mat imageContours = Mat::zeros(inImgTemp.size(), CV_8UC1);
    Mat Contours = Mat::zeros(inImgTemp.size(), CV_8UC1);  //绘制


    for (int i = 0; i<contours.size(); i++)
    {
        //contours[i]代表的是第i个轮廓,contours[i].size()代表的是第i个轮廓上所有的像素点数
        for (int j = 0; j<contours[i].size(); j++)
        {

            //绘制出contours向量内所有的像素点
            Point P = Point(contours[i][j].x, contours[i][j].y);
            Contours.at<uchar>(P) = 255;
        }


        //绘制轮廓
        drawContours(imageContours, contours, i, Scalar(255), FILLED, 8);
    }


    // 遍历每个轮廓,寻找其凸包  
    vector<vector<Point> >hull(contours.size());
    for (unsigned int i = 0; i < contours.size(); i++)
    {
        convexHull(Mat(contours[i]), hull[i], false);
    }


    // 绘出轮廓及其凸包  
    Mat drawing = Mat::zeros(inImgTemp.size(), CV_8UC3);
    for (unsigned int i = 0; i< contours.size(); i++)
    {
        Scalar color = Scalar(0, 0, 255);
        drawContours(drawing, contours, i, color, FILLED, 8, vector<Vec4i>(), 0, Point());
        drawContours(drawing, hull, i, color, FILLED, 8, vector<Vec4i>(), 0, Point());
    }


    imshow("Contours Image", imageContours); //轮廓
    imshow("Point of Contours", Contours);   //向量contours内保存的所有轮廓点集
    // 显示效果图  
    imshow("drawing", drawing);


    waitKey(0);
    return 0;
}


----------

3. 绘制轮廓:drawContours()函数

(1)函数的调用形式:

扫描二维码关注公众号,回复: 52249 查看本文章
void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() )

函数参数详解:

  • 第一个参数image:目标图像
  • 第二个参数contours:输入的轮廓组,每一组轮廓由点vector构成
  • 第三个参数contourIdx:指明画第几个轮廓,如果该参数为负值,则画全部轮廓
  • 第四个参数color:为轮廓的颜色
  • 第五个参数thickness:为轮廓的线宽,默认值为1
    • 如果为负值 或 FILLED 表示填充轮廓内部
  • 第六个参数lineType:线型,默认值为8
  • 第七个参数hierarchy:为轮廓结构信息
  • 第八个参数maxLevel:用于绘制轮廓的最大等级,有默认值INT_MAX
  • 第九个参数offset:可选的轮廓偏移参数,有默认值Point()。

猜你喜欢

转载自blog.csdn.net/Tian_fourpieces/article/details/80055632
今日推荐