1. 查找图像轮廓:findContours函数
函数 cv2.findContours()的语法格式为:
image, contours, hierarchy = cv2.findContours( image, mode, method)
式中的返回值为:
- image:与函数参数中的原始图像 image 一致。
- contours:返回的轮廓。
- hierarchy:图像的拓扑信息(轮廓层次)。
式中的参数为: - image:原始图像。8 位单通道图像,所有非零值被处理为 1,所有零值保持不变。也就 是说灰度图像会被自动处理为二值图像。在实际操作时,可以根据需要,预先使用阈值 处理等函数将待查找轮廓的图像处理为二值图像。
- mode:轮廓检索模式。
- method:轮廓的近似方法。
1.1 返回值image
该返回值与参数 image 是一致的,就是原始输入图像。
1.2 返回值contours
该返回值返回的是一组轮廓信息,每个轮廓都是由若干个点所构成的。
(1)type 属性
返回值 contours 的 type 属性是 list 类型,list 的每个元素都是图像的一个轮廓,用 Numpy中的 ndarray 结构表示。
(2)轮廓的个数
print (len(contours))
(3)每个轮廓的点数
每一个轮廓都是由若干个像素点构成的,点的个数不固定,具体个数取决于轮廓的形状。
print(contours[0].shape)
(4)轮廓内的点
使用如下语句,可以获取轮廓内第 0 个轮廓中具体点的位置属性:
print (contours[0]) #打印第0个轮廓中的像素点
1.3 返回值hierarchy
每个轮廓 contours[i]对应 4 个元素来说明当前轮廓的层次关系。其形式为:
[Next,Previous,First_Child,Parent]式中各元素的含义为:
- Next:后一个轮廓的索引编号。
- Previous:前一个轮廓的索引编号。
- First_Child:第 1 个子轮廓的索引编号
- Parent:父轮廓的索引编号。
使用 print 语句可以查看 hierarchy 的值:
print(hierarchy)
1.4 参数image
一般情况下,都是将图像处理为二 值图像后,再将其作为 image 参数使用的。
1.5 参数mode
- cv2.RETR_EXTERNAL:只检测外轮廓。
- cv2.RETR_LIST:对检测到的轮廓不建立等级关系。
- cv2.RETR_CCOMP:检索所有轮廓并将它们组织成两级层次结构。上面的一层为外边界,下面的一层为内孔的边界。如果内孔内还有一个连通物体,那么这个物体的边界仍
然位于顶层。 - cv2.RETR_TREE:建立一个等级树结构的轮廓。
1.6 参数method
- cv2.CHAIN_APPROX_NONE:存储所有的轮廓点,相邻两个点的像素位置差不超过 1, 即 max(abs(x1-x2),abs(y2-y1))=1。
- cv2.CHAIN_APPROX_SIMPLE:压缩水平方向、垂直方向、对角线方向的元素,只保 留该方向的终点坐标。例如,在极端的情况下,一个矩形只需要用 4 个点来保存轮廓信 息。
在使用函数 cv2.findContours()查找图像轮廓时,需要注意以下问题:
- 待处理的源图像必须是灰度二值图。因此,在通常情况下,都要预先对图像进行阈值分 割或者边缘检测处理,得到满意的二值图像后再将其作为参数使用。
- 在 OpenCV 中,都是从黑色背景中查找白色对象。因此,对象必须是白色的,背景必须 是黑色的。
2. 绘制图像轮廓:drawContours函数
在 OpenCV 中,可以使用函数 cv2.drawContours()绘制图像轮廓。该函数的语法格式是:
image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]] )```
其中,函数的返回值为 image,表示目标图像,即绘制了边缘的原始图像。
该函数有如下参数:
- image:待绘制轮廓的图像。需要注意,函数
cv2.drawContours()会在图像 image 上直接 绘制轮廓。也就是说,在函数执行完以后,image 不再是原始图像,而是包含了轮廓的 图像。因此,如果图像 image 还有其他用途的话,则需要预先复制一份,将该副本图像 传递给函数cv2.drawContours()使用。 - contours:需要绘制的轮廓。该参数的类型与函数
cv2.findContours()的输出 contours 相 同,都是 list 类型。 - contourIdx:需要绘制的边缘索引,告诉函数
cv2.drawContours()要绘制某一条轮廓还是 全部轮廓。如果该参数是一个整数或者为零,则表示绘制对应索引号的轮廓;如果该值 为负数(通常为“-1”),则表示绘制全部轮廓。 - color:绘制的颜色,用 BGR 格式表示。
- thickness:可选参数,表示绘制轮廓时所用画笔的粗细。如将该值设置为“-1”,则表示要绘制实心轮廓。
- lineType:可选参数,表示绘制轮廓时所用的线型。关于参数 color、thickness 和 lineType的具体介绍,可参考第 19 章。
- hierarchy:对应函数
cv2.findContours()所输出的层次信息。 - maxLevel:控制所绘制的轮廓层次的深度。如果值为 0,表示仅仅绘制第 0 层的轮廓;如果值为其他的非零正数,表示绘制最高层及以下的相同数量层级的轮廓。
- offset:偏移参数。该参数使轮廓偏移到不同的位置展示出来。
3. 轮廓实例
【例 12.1】绘制一幅图像内的所有轮廓。
import cv2
o = cv2.imread("/Users/zhaofeier/Desktop/源代码及图像/chapter12/contours.bmp")
cv2.imshow("original",o)
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, #? binary没有返回值
cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
o=cv2.drawContours(o,contours,-1,(0,0,255),5) #?轮廓的颜色被设置为红色即(0,0,255),参数thickness(轮廓线条的粗细)被设置为“5”。
cv2.imshow("result",o)
cv2.waitKey()
cv2.destroyAllWindows()
【例 12.2】逐个显示一幅图像内的边缘信息。
import numpy as np
img = cv2.imread("/Users/zhaofeier/Desktop/源代码及图像/chapter12/contours.bmp")
cv2.imshow("original",img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours,hierarchy = cv2.findContours(binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
contoursImg = []
for i in range(len(contours)):
temp = np.zeros(img.shape,np.uint8)
contoursImg.append(temp)
contoursImg[i] = cv2.drawContours(contoursImg[i],contours,i,(0,0,255),5)
cv2.imshow("result="+str(i),contoursImg[i])
cv2.waitKey()
cv2.destroyAllWindows()
【例 12.3】使用轮廓绘制功能,提取前景对象。
img = cv2.imread("/Users/zhaofeier/Desktop/源代码及图像/chapter12/loc3.jpg")
cv2.imshow("orginal",img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours,hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
mask = np.zeros(img.shape,np.uint8)
mask = cv2.drawContours(mask,contours,-1,(255,255,255),-1)
#? 参数 thickness 设置为“-1”,得到了前景对象的实心轮廓mask
cv2.imshow("mask",mask)
loc = cv2.bitwise_and(img,mask)
#? 将原始图像 o 与实心轮廓 mask 进行“按位与”运算
cv2.imshow("location",loc)
cv2.waitKey()
cv2.destroyAllWindows()
- 左图是原始图像,其前景对象是一朵小花。
- 中间的图像是从原始图像得到的小花的实心轮廓。
- 右图是提取的前景对象小花。
7012

被折叠的 条评论
为什么被折叠?



