OpenCV findContours函数

简介: OpenCV findContours函数

findContours()函数


函数功能


检测出物体的轮廓


函数原型


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


参数说明


  • image:单通道图像矩阵,可以是灰度图,但更常用的是二值图像,一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像;


  • contours:contours定义为“vector<vector> contours”,是一个双重向量(向量内每个元素保存了一组由连续的Point构成的点的集合的向量),每一组点集就是一个轮廓,有多少轮廓,contours就有多少元素;


  • hierarchy:hierarchy定义为“vector<Vec4i> hierarchy”,Vec4i的定义:typedef Vec<int, 4> Vec4i;(向量内每个元素都包含了4个int型变量),所以从定义上看,hierarchy是一个向量,向量内每个元素都是一个包含4个int型的数组。向量hierarchy内的元素和轮廓向量contours内的元素是一一对应的,向量的容量相同。hierarchy内每个元素的4个int型变量是hierarchy[i][0] ~ hierarchy[i][3],分别表示当前轮廓 i 的后一个轮廓、前一个轮廓、父轮廓和内嵌轮廓的编号索引。如果当前轮廓没有对应的后一个轮廓、前一个轮廓、父轮廓和内嵌轮廓,则相应的hierarchy[i][*]被置为-1。


  • mode:定义轮廓的检索模式,取值如下:


CV_RETR_EXTERNAL:只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略;
CV_RETR_LIST:检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立,没有等级关系,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓,所以hierarchy向量内所有元素的第3、第4个分量都会被置为-1,具体下文会讲到;
CV_RETR_CCOMP: 检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层,若外围内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层;
CV_RETR_TREE: 检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。


  • method:定义轮廓的近似方法,取值如下:


CV_CHAIN_APPROX_NONE:保存物体边界上所有连续的轮廓点到contours向量内;
CV_CHAIN_APPROX_SIMPLE:仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留;
CV_CHAIN_APPROX_TC89_L1:使用teh-Chinl chain 近似算法;
CV_CHAIN_APPROX_TC89_KCOS:使用teh-Chinl chain 近似算法。


  • offset:Point偏移量,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓点上加上该偏移量,并且Point还可以是负值!


测试:mode与method取值问题


通过调整第四个参数mode——轮廓的检索模式、第五个参数method——轮廓的近似方式和不同的偏移量Point(),就可以得到不同效果。


检测最外层轮廓,并且保存轮廓上所有点


一、mode取值“CV_RETR_EXTERNAL”,method取值


“CV_CHAIN_APPROX_NONE”,即只检测最外层轮廓,并且保存轮廓上所有点:

轮廓:



只有最外层的轮廓被检测到,内层的轮廓被忽略


contours向量内所有点集:



保存了所有轮廓上的所有点,图像表现跟轮廓一致


hierarchy向量:



重温一下hierarchy向量————向量中每个元素的4个整形分别对应当前轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。


本次参数配置下,hierarchy向量内有3个元素,分别对应于3个轮廓。以第2个轮廓(对应向量内第1个元素)为例,


内容为[2,0,-1,-1], “2”表示当前轮廓的后一个轮廓的编号为2,“0”表示当前轮廓的前一个轮廓编号为0,其后2个“-1”表示为空,因为只有最外层轮廓这一个等级,所以不存在父轮廓和内嵌轮廓。


检测所有轮廓,但各轮廓之间彼此独立,不建立等级关系,并且仅保存轮廓上拐点信息


二、 mode取值“CV_RETR_LIST”,method取值“CV_CHAIN_APPROX_SIMPLE”,即检测所有轮廓,但各轮廓之间彼此独立,不建立等级关系,并且仅保存轮廓上拐点信息:



检测到的轮廓跟上文“一”中是一致的,不再显示。


contours向量内所有点集:



contours向量中所有的拐点信息得到了保留,但是拐点与拐点之间直线段的部分省略掉了。


hierarchy向量(截取一部分):



本次参数配置下,检测出了较多轮廓。第1、第2个整形值分别指向上一个和下一个轮廓编号,由于本次配置mode取值“RETR_LIST”,各轮廓间各自独立,不建立等级关系,所以第3、第4个整形参数为空,设为值-1。


检测所有轮廓,轮廓间建立外层、内层的等级关系,并且保存轮廓上所有点


三、mode取值“CV_RETR_TREE”,method取值“CV_CHAIN_APPROX_NONE”,即检测所有轮廓,轮廓间建立外层、内层的等级关系,并且保存轮廓上所有点。



contours向量内所有点集:



所有内外层轮廓都被检测到,contours点集组成的图形跟轮廓表现一致。


hierarchy向量(截取一部分)



本次参数配置要求检测所有轮廓,每个轮廓都被划分等级,最外围、第一内围、第二内围等等,所以除第1个最后一个轮廓外,其他轮廓都具有不为-1的第3、第4个整形参数,分别指向当前轮廓的父轮廓、内嵌轮廓索引编号。


Point()偏移量设置


使用三中的参数配置,设置偏移量Point为Point(45,30)。


此时轮廓图像为:




可以看到轮廓图像整体向右下角有一个偏转,偏转量就是设置的(45,30)。


这个偏移量的设置不能过大或过小(负方向上的过小),若图像上任一点加上该偏移量后超出图像边界,程序会内存溢出报错。



另外,绘制轮廓的函数drawContours中最后一个参数是一个Point类型的offset,这个offset跟findContours函数中的offset含义一致,设置之后所绘制的轮廓是原始轮廓上所有像素点加上该偏移量offset后的效果。


当所分析图像是另外一个图像的ROI的时候,这个offset偏移量就可以大显身手了。通过加减这个偏移量,就可以把ROI图像的检测结果投影到原始图像对应位置上。


相关文章
|
2月前
|
监控 API 计算机视觉
OpenCV这么简单为啥不学——1.3、图像缩放resize函数
OpenCV这么简单为啥不学——1.3、图像缩放resize函数
41 0
|
6月前
|
计算机视觉
OpenCV-图像翻转函数cv::filp
OpenCV-图像翻转函数cv::filp
|
2月前
|
人工智能 Linux API
OpenCV这么简单为啥不学——1.1、图像处理(灰度图、模糊图片、GaussianBlur函数、提取边缘、边缘膨胀、边缘细化)
OpenCV这么简单为啥不学——1.1、图像处理(灰度图、模糊图片、GaussianBlur函数、提取边缘、边缘膨胀、边缘细化)
46 0
|
6月前
|
计算机视觉 C++
OpenCV-计时函数cv::getTickCount&cv::getTickFrequency
OpenCV-计时函数cv::getTickCount&cv::getTickFrequency
|
2月前
|
监控 算法 Serverless
OpenCV这么简单为啥不学——1.12、使用ssim函数对两张照片进行相似度分析
OpenCV这么简单为啥不学——1.12、使用ssim函数对两张照片进行相似度分析
43 0
|
2月前
|
监控 API 计算机视觉
OpenCV这么简单为啥不学——1.6、图像旋转与翻转(rotate函数、imutils环境安装、imutils任意角度旋转)
OpenCV这么简单为啥不学——1.6、图像旋转与翻转(rotate函数、imutils环境安装、imutils任意角度旋转)
33 0
|
2月前
|
监控 API 计算机视觉
OpenCV这么简单为啥不学——1.4、基础标识绘制(绘制线line函数、rectangle函数绘制四边形、circle函数绘制圆形、putText函数绘制文字、putText绘制中文文字)
OpenCV这么简单为啥不学——1.4、基础标识绘制(绘制线line函数、rectangle函数绘制四边形、circle函数绘制圆形、putText函数绘制文字、putText绘制中文文字)
28 0
|
2月前
|
监控 API 计算机视觉
OpenCV这么简单为啥不学——2、逐帧播放视频(VideoCapture函数、waitKey函数、0xFF == ord(‘1‘))
OpenCV这么简单为啥不学——2、逐帧播放视频(VideoCapture函数、waitKey函数、0xFF == ord(‘1‘))
33 0
|
2月前
|
监控 API 图形学
OpenCV这么简单为啥不学——1、基础环境与imread函数
OpenCV这么简单为啥不学——1、基础环境与imread函数
30 0
|
4月前
|
计算机视觉 Python
OpenCV中阈值处理函数和二值化、反二值化的讲解及实战(附Python源码)
OpenCV中阈值处理函数和二值化、反二值化的讲解及实战(附Python源码)
99 0