opencv-python 详解轮廓及findContours()、drawContours()函数_python opencv findcontours
(敲黑板划重点)理解轮廓层级、等级:
轮廓的检索方法模式4种:
轮廓的近似办法有4种:
轮廓的定义
轮廓是一系列相连的点组成的曲线,代表了物体的基本外形。
轮廓和边缘的区别
谈起轮廓不免想到边缘,它们确实很像。简单的说,轮廓是连续的,边缘并不全都连续(下图)。其实边缘主要是作为图像的特征使用,比如可以用边缘特征可以区分脸和手,而轮廓主要用来分析物体的形态,比如物体的周长和面积等,可以说边缘包括轮廓。

寻找轮廓的方法和经验
寻找轮廓的操作一般基于二值化图,所以通常会使用阈值分割或Canny边缘检测先得到二值图。
经验之谈:寻找轮廓是针对白色物体的,一定要保证物体是白色,而背景是黑色,不然很多人在
寻找轮廓时会找到图片最外面的一个框。
先看一个demo,图片:

代码:
import cv2
img = cv2.imread('handwriting.jpg')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 使用Otsu自动阈值,注意用的是cv2.THRESH_BINARY_INV
ret, thresh = cv2.threshold(
img_gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# cv2.imshow("thresh", thresh)
"""
寻找轮廓方法三个参数:输入图像,轮廓检索模式,轮廓近似方法
返回值contours是轮廓本身contours,还有一个是每条轮廓对应的属性hierarchy,下边详解
"""
contours, hierarchy = cv2.findContours(
thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print(len(contours)) # 结果应该为2,两个轮廓
cnt = contours[1]
"""
绘制轮廓:
第一个参数是一张图片,可以是原图或者其他。
第二个参数是轮廓,也可以说是cv2.findContours()找出来的点集,一个列表。
第三个参数是对轮廓(第二个参数)的索引,当需要绘制独立轮廓时很有用,若要全部绘制可设为-1。
接下来的参数是轮廓的颜色和厚度。
"""
cv2.drawContours(img, [cnt], 0, (0, 0, 255), 2)
cv2.imshow('contours', img)
cv2.waitKey(0)
findContours()详解
使用 cv2.findContours() 寻找轮廓,findContours()有三个参数:输入图像,轮廓检索模式,轮廓近似方法,返回值contours是轮廓本身contours,还有一个是每条轮廓对应的属性hierarchy,下边详解 。

(敲黑板划重点)理解轮廓层级、等级:

图中总共有8条轮廓,2和2a分别表示外层和里层的轮廓,3和3a也是一样。从图中看得出来:
这里面
OpenCV
关注的就是两个概念:同一轮廓等级和轮廓间的子属关系。
如果我们打印出 cv2.findContours() 函数的返回值hierarchy,会发现它是一个包含4个值的数组:
[Next, Previous, First Child, Parent]
比如2a的父轮廓是2,Parent=2;轮廓2没有父轮廓,所以Parent=-1。
经验之谈:
OpenCV
中找到的轮廓序号跟前面讲的不同噢,如下图:

轮廓的检索方法模式4种:


因为没有从属关系,所以轮廓0的下一条是1,1的下一条是2……
经验之谈:如果你不需要轮廓层级信息的话,cv2.RETR_LIST
更推荐使用,因为性能更好。

图中括号里面1代表外层轮廓,2代表里层轮廓。比如说对于轮廓2,Next就是4,Previous是1,它有里层的轮廓3,所以First Child=3,但因为只有两个层级,它本身就是外层轮廓,所以Parent=-1。大家可以针对其他的轮廓自己验证一下。
作者:2501_90339150