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
!-- p,>!-- p,>!-- p,>!-- p,>以上是关于opencv findContours函数的主要内容,如果未能解决你的问题,请参考以下文章
OpenCV示例学习笔记-contours2.cpp-通过findContours 函数实现轮廓提取