一、返回值概述
cv2.findcontours函数用于检测二值图像中的轮廓。这个函数返回三个参数,分别是:
image, contours, hierarchy = cv2.findContours(image, mode, method)
其中,image是输入的二值图像;contours是一个列表,其中包含检测出来的轮廓;hierarchy描述了轮廓之间的关系。
二、contours参数详解
上面提到,contours是一个列表,其中包含检测出来的轮廓。每一个轮廓都是由一系列点组成的,可以使用cv2.drawContours函数将其画出。但是在实际应用中,我们还需要进一步了解这个contours参数。
首先,我们可以通过len(contours)来获取图像中的轮廓数量,也可以使用cv2.drawContours函数画出指定的轮廓。假设我们想要画出第二个轮廓,代码如下:
cv2.drawContours(img, [contours[1]], -1, (0,255,0), 3)
如果想要获取第一个轮廓的面积,可以使用cv2.contourArea函数。同理,我们还可以获取轮廓的周长(cv2.arcLength)、边界矩形(cv2.boundingRect)、最小闭合圆(cv2.minEnclosingCircle)等信息。
三、hierarchy参数详解
在返回值中,hierarchy描述了轮廓之间的关系。hierarchy是一个形状和contours一样的多维数组,每一行的元素有四个分量,分别表示后一个轮廓、前一个轮廓、父轮廓和内部轮廓。如果当前轮廓没有对应的后一个、前一个、父轮廓或内部轮廓,那么对应分量的值为-1。
对于复杂的轮廓,在使用cv2.drawContours函数时,我们可以通过注释掉一部分代码,只画出特定的轮廓。如果想画出所有的轮廓,可以使用以下代码:
cv2.drawContours(img, contours, -1, (0,255,0), 3)
如果想提取某一个轮廓的所有子轮廓,可以使用hierarchy参数。以下是获取第一个轮廓的子轮廓的示例代码:
child_ids = hierarchy[0,:,2]
child_contours = [contours[i] for i in child_ids if i != -1]
四、轮廓近似
cv2.findContours返回的轮廓是由一系列点组成的,但是实际应用中,我们往往需要将轮廓进行近似,以便用更少的点来表示轮廓。这个近似过程可以通过cv2.approxPolyDP实现,它需要两个参数:输入的轮廓和近似程度(epsilon)。近似的结果是一系列点,可以使用cv2.drawContours函数将其画出。
以下是进行近似的示例代码:
epsilon = 0.01 * cv2.arcLength(contours[0], True)
approx = cv2.approxPolyDP(contours[0], epsilon, True)
cv2.drawContours(img, [approx], -1, (0, 0, 255), 3)
五、轮廓特征提取
在检测轮廓时,如果我们想要进行轮廓匹配或者分类,那么需要从轮廓中提取一些特征。常见的特征包括:轮廓面积、周长、重心、边界框、外接圆、最大直径等。以下是获取轮廓面积和周长的示例代码:
area = cv2.contourArea(contours[0])
perimeter = cv2.arcLength(contours[0], True)
需要注意的是,这些特征提取函数都需要传入轮廓作为参数。
六、小结
本文深入探究了cv2.findContours函数返回值中的contours和hierarchy参数,并且介绍了轮廓近似和轮廓特征提取。通过这些知识点,我们可以更好地理解轮廓检测的原理,并且在实际应用中更加灵活地使用轮廓。