在OpenCV中处理结构分析和形状描述(Structural Analysis and Shape Descriptors),大部分跟contours相关。
轮廓线就是一条连接所有边界点的曲线,其实也就是两点相连构成的list。
(部分翻译的外文blog)
“The contours are a useful tool for shape analysis and object detection and recognition”
`import numpy as np
import cv2
#找出下图的轮廓线。
im = cv2.imread('test.jpg')
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)`
轮廓线生成的函数findContours,需要考虑3点:
1、使用binary images
2、转换threshold
3、轮廓是指白色物体的轮廓,背景是黑色。
不同的物体表示成不同的list,list里保存每个轮廓点。要知道有几个物体,可以使用len查看。
>>>len(contours)
#output = 1 using the above picture
>>> cnt = contours[0]
>>> len(cnt)
#轮廓线线宽3pixel
cv2.drawContours(im,contours,-1,(0,255,0),3)
#轮廓线线宽-1,表示填充物体
cv2.drawContours(im,contours,-1,(0,255,0),-1)
#可以单独画其中某一个物体的轮廓线,用[cnt]替换contours
cv2.drawContours(im,[cnt],0,(255,0,0),-1)
mask是指制图区域,或者ROI(region of interest)。
for h,cnt in enumerate(contours):
mask = np.zeros(imgray.shape,np.uint8)
cv2.drawContours(mask,[cnt],0,255,-1)
mean = cv2.mean(im,mask = mask)
这个函数可以计算形状的中心点、面积等性质。
`
moments = cv2.moments(cnt)
`
{'mu02': 10888082.359906793, 'mu03': 0.005234025965704581, 'm11': 368666693.125,
'nu02': 0.10815497152071127, 'm12': 69763579350.98334, 'mu21': 101313.30416250229, 'mu20': 6674463.831166983,
'nu20': 0.06629968636479547, 'm30': 84692116672.95001, 'nu21': 1.0046975468372928e-05, 'mu11': -1980114.5675549507,
'mu12': -33122544.260385513, 'nu11': -0.019669141689288665, 'nu12': -0.0032846761082870463, 'm02': 352044973.5833333,
'm03': 68983799276.15001, 'm00': 10033.5, 'm01': 1850134.5, 'mu30': 8633090.369003296, 'nu30': 0.0008561209988226333,
'm10': 2010061.8333333333, 'm20': 409360323.5833333, 'm21': 74691021944.88333}
其中‘m00’表示面积
##Contour Area函数
计算contour包含的面积,也就是像素点的个数。
area = cv2.contourArea(cnt)
#计算长度
perimeter = cv2.arcLength(cnt,True)
该函数可以减少轮廓边的小毛刺
#乘法前面的参数叫epsilon,表示原始轮廓线到新轮廓线的最大距离,可以控制新轮廓线的形状。
approx = cv2.approxPolyDP(cnt,0.1*cv2.arcLength(cnt,True),True)
凸壳可以找到物体最大外接凸多边形。
#这个函数比较复杂,用到的时候需要再具体看看。
#以下是函数表达式。
hull = cv2.convexHull(points[, hull[, clockwise[, returnPoints]]])
#正常的获取轮廓的凸壳可以直接调用:
hull = cv2.convexHull(cnt)
#还有一个参数returnPoints,表示返回的是cnt的列表序号而不是直接返回坐标,默认是true,返回的坐标
hull = cv2.convexHull(cnt,returnPoints = False)
#返回真or假
k = cv2.isContourConvex(cnt)
第一种:外接矩形框,矩形是跟图片平行的,(x,y)框的左上坐标,(w,h)表示宽度和高度。
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2)
第二种:最小外接矩形框
#返回值 Box2D structure - (x,y),(w,h),theta.
矩形中心点,theta旋转角度
rect = cv2.minAreaRect(cnt)
box = cv2.cv.BoxPoints(rect)
box = np.int0(box)
cv2.drawContours(im,[box],0,(0,0,255),2)
#BoxPoints是把中心点,长宽角度转换成四个角点坐标。
最小外接圆形
(x,y),radius = cv2.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
cv2.circle(im,center,radius,(0,255,0),2)
ellipse = cv2.fitEllipse(cnt)
cv2.ellipse(im,ellipse,(0,255,0),2)