opencv findContours函数

Posted peimingzhang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opencv findContours函数相关的知识,希望对你有一定的参考价值。

一、前言

  findContours函数的参数在众多博客中都有详细介绍,本篇随笔主要针对个别函数参数做说明,并记录相关的输出参数的部分细节

二、函数介绍

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

  contours为获取的轮廓信息,轮廓信息定义务必是vector<vector<Point>> 形式的

  hierarchy为层级关系,定义为vector<Vec4i>和Mat都可以。每个轮廓有四个层级信息,分别为:上一个轮廓序号、下一个轮廓序号、子轮廓序号、父轮廓序号

  mode 官方是“轮廓检索算法的模式”,可以理解为获取怎样的层级信息

  method 轮廓近似模式

  offset

三、基本效果展示

  基本代码:

    Mat img = imread("../contours.bmp",IMREAD_GRAYSCALE);
    imshow("source img",img);
    vector<vector<Point>> vContours;
    Mat mContourShow = Mat::zeros(img.size(),CV_8U);
    findContours(img,vContours,RETR_LIST,CHAIN_APPROX_NONE);
    drawContours(mContourShow,vContours,-1,Scalar(255));
    imshow("Contours",mContourShow);
    waitKey();

  代码运行结果:      

     技术图片

四、个别参数的细节区分

  部分代码:

1      vector<Vec4i> mHierarchy;
2     vector<vector<Point>> vContours;
3     Mat mContourShow = Mat::zeros(img.size(),CV_8UC3);
4     findContours(img,vContours,mHierarchy,RETR_EXTERNAL,CHAIN_APPROX_NONE,Point(0,0));
5     for(int i = 0; i<vContours.size(); i++){
6         drawContours(mContourShow,vContours,i,Scalar(0,255,255),1,LINE_8);
7         putText(mContourShow,to_string(mHierarchy[i][0]).append(",").append(to_string(mHierarchy[i][1])),vContours[i][0],FONT_HERSHEY_SCRIPT_SIMPLEX,0.5,Scalar(255,255,0),1);
8     }

  4.1 mode层级信息

技术图片 技术图片

技术图片 技术图片注:图中我打的两个数字标签为层级关系的第一个数和第二个数

  mode分别为RETR_EXTERNAL(左上)、RETR_LIST(右上)、RETR_CCOMP(左下)、RETR_TREE(右下)时

的层级关系数组分别为

1,-1,-1,-1      1,-1,-1,-1          1,-1,-1,-1          7,-1,1,-1

-1,0,-1,-1      2,0,-1,-1           4,0,2,-1           6,-1,2,0

          3,1,-1,-1           3,-1,-1,1          -1,-1,3,1

          4,2,-1,-1           -1,2,-1,1          4,-1,-1,2

          5,3,-1,-1           7,1,5,-1           -1,3,5,2

          6,4,-1,-1           6,-1,-1,4          -1,-1,-1,4

 

          7,5,-1,-1           -1,5,-1,4          -1,1,-1,0

          -1,6,-1,-1          -1,4,-1,-1          -1,0,-1,-1

RETR_EXTERNAL模式是只找最外层的轮廓

RETR_LIST模式是找到所有的轮廓,但是不提供层级关系

RETR_CCOMP模式是找到所有轮廓,层级只有两层(外轮廓和洞,洞里面再有轮廓按照外轮廓算,表现在层级关系上为:父轮廓无父轮廓,子轮廓无子轮廓),注意这里父轮廓只能指定一个子轮廓,但是多个子轮廓可以指定同一个父轮廓

RETR_TREE模式是以树状梳理所有轮廓的关系

RETR_FLOODFILL官网也没有介绍,我这里用上面的图得到的效果轮廓和层级结果也不好,这里暂时不深究了

PS:RETR_CCOMP模式可以对打了lable的图片(比如通过connectcomponent函数或者watershed函数获得的结果)进行轮廓识别

 

4.2 method拟合方法

此处我换了原图,下列图片从左到右依次为:原图、CHAIN_APPROX_NONE方法、CHAIN_APPROX_SIMPLE方法、CHAIN_APPROX_TC89_L1方法、CHAIN_APPROX_TC89_KCOS方法(点集边上的数字是点集个数)

技术图片技术图片技术图片技术图片技术图片

 

CHAIN_APPROX_NONE是不做处理

CHAIN_APPROX_SIMPLE会将直线和对角线优化掉

CHAIN_APPROX_TC89_L1和CHAIN_APPROX_TC89_KCOS采用了近似算法

PS:如果需要真实的点集就使用前两种方法。

 

五、其他

另外再补充几点:

1、findContours找点集,对于“洞”的轮廓是4邻域连续,对于外轮廓是16邻域连续(如下图所示),当用CHAIN_APPROX_SIMPLE简化点时,矩形洞会简化为8个点

技术图片

2、所有边界点集都是位于白色区域内的,不会因为它是洞就落在黑色区域上

 

                                                                                        代码使用opencv版本:4.1.0


以上是关于opencv findContours函数的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV示例学习笔记-contours2.cpp-通过findContours 函数实现轮廓提取

将OpenCV函数findContours()得到的每一个轮廓单独绘制并保存为图片文件的Python代码

findContours 在 opencv 中找不到轮廓

OpenCV findContours 函数问题

opencv findContours函数

youcans 的 OpenCV 例程200篇194.寻找图像轮廓(cv.findContours)