轮廓的生成
主要涉及两个函数findContours(),分别用于获得轮廓和绘制轮廓。
先看第一个函数,用途是获取轮廓,函数原型是:cv2.findContours
contours, hierarchy = cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]])
代码示例:
contours,hierarchy = cv2.findContours(thres,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
print(hierarchy)
[[[ 1 -1 -1 -1]
[ 2 0 -1 -1]
[ 3 1 -1 -1]
[-1 2 -1 -1]]]
参数解读:
-
image:输入该函数的图片必须是二值图,要想从灰度图和彩色图获得二值图,可使用 compare, inRange, threshold , adaptiveThreshold, Canny等方法。
-
hierarchy:可选的输出向量,包含图像轮廓层级结构的信息(如果轮廓a被轮廓b包围,则称a是b的子轮廓;如果二者互不干扰,则称两者处于同一层级),向量中元素的个数和轮廓的个数一致,每个元素包含四个值
[next,previous,child,parent]。next/previous表示同一层级的下/上一条轮廓,child表示该轮廓的第一个子轮廓,parent表示该轮廓的父轮廓。 -
contours:列表,包含所有轮廓的坐标。
-
mode:轮廓检索模式,参考RetrievalModes,一般使用
cv2.RETR_TREE,保留轮廓的所有层级信息。 -
method:轮廓近似方法,参考ContourApproximationModes。
-
offset:可选,表示轮廓每个点的偏移量。
轮廓的绘制
第二个函数cv2.drawContours用于绘制轮廓,函数原型是:
image = cv.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]] )
代码示例:cv2.drawContours(img,contours,-1,(0,0,255))

参数解读:
- image:输入图片。
- contours:轮廓数组。
- contourIdx:轮廓下标,如果为负值表示绘制所有轮廓。
- color:轮廓颜色。
- thickness:轮廓粗细。
- lineType:轮廓线条类型。
- hierarchy:轮廓层级。
- maxlevel:当hierarchy参数被起用时,maxlevel参数才有效。如果设置为0,表示只绘制最底层轮廓,设置为1,表示再绘制上一层级的轮廓,设置为2,再绘制上上层级的轮廓,以此类推。
maxlevel参数示例:对于下面一张图片

运行代码,可知图中轮廓有672个层级。
contours,hierarchy = cv2.findContours(thres,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
print(hierarchy.shape[1]) #672
获得轮廓和轮廓层级后,使用drawContours函数绘制轮廓。设置maxlevel=1时,结果如下:

设置maxlevel=50时,绘制的轮廓如下:

轮廓的特征
对于以下轮廓:

用contourArea()计算轮廓面积,函数原型是:
retval = cv2.contourArea( contour[, oriented] )
代码示例:
area = cv2.contourArea(cnt,oriented=False)
print(area) #4386.5
oriented参数用于判断轮廓是顺时针还是逆时针,当oriented=True时,返回一个有符号数。
area = cv2.contourArea(cnt,oriented=True)
print(area) #-4386.5
用arcLength()计算轮廓周长或曲线长度,函数原型是:
retval = cv2.arcLength(curve, closed)
closed参数表示曲线是否闭合,代码示例:
primeter = cv2.arcLength(cnt,True)
print(primeter) #585.7716399431229
使用moment()函数返回一个字典,存储轮廓的图像矩(image moment),关于图像矩的概念,参考Image moment
函数原型:
retval = cv.moments(array[, binaryImage])
代码示例:
moment = cv2.moments(cnt)
print(type(moment))
{'m00': 4386.5, 'm10': 901090.1666666666, 'm01': 1236138.8333333333, 'm20': 188838763.0833333, 'm11': 257499174.375, 'm02': 356134618.0833333, 'm30': 40295080579.05, 'm21': 54657354898.55, 'm12': 75190459423.68333, 'm03': 104935417053.65001, 'mu20': 3733670.534977913, 'mu11': 3567213.2781181633, 'mu02': 7784175.754667103, 'mu30': -30805687.716514587, 'mu21': -23983275.523046732, 'mu12': 21521982.85149741, 'mu03': 187559951.4465332, 'nu20': 0.19404377951994134, 'nu11': 0.185392776452854, 'nu02': 0.4045538752636705, 'nu30': -0.024173279544299146, 'nu21': -0.018819720206919972, 'nu12': 0.016888339341892225, 'nu03': 0.14717863724891386}
字典中每个参数的计算方式,参考cv::Moments。
使用boundingRect()函数返回轮廓的最大外接矩形,函数原型是:
retval = cv.boundingRect(array)
代码示例:
rect = cv2.boundingRect(cnt)
x,y,w,h = rect
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
结果如图所示:

使用minAreaRect()函数找到最小外接矩形,代码示例:
min_rect = cv2.minAreaRect(cnt)
box = np.int0(cv2.boxPoints(min_rect)) # 矩形的四个角点取整
cv2.drawContours(img, [box], 0, (255, 0, 0), 2)
结果如下:

使用minEnclosingCircle()找到最小外接圆,代码示例:
(x, y), radius = cv2.minEnclosingCircle(cnt)
(x, y, radius) = np.int0((x, y, radius)) # 圆心和半径取整
cv2.circle(img, (x, y), radius, (0, 0, 255), 2)
结果如下:

本文详细介绍了在OpenCV-Python中如何生成、绘制轮廓,包括使用函数获取和绘制轮廓的方法,以及如何利用轮廓特性计算面积、周长、图像矩、最大外接矩形和最小外接圆等关键信息。

1842

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



