《OpenCV》☞ Contours

1.Start

          Contours可被认为是一条连续点点点(这些点具有相同的颜色或亮度)沿边界相连的曲线。Contours对与形状分析和目标的检测、识别是一种有用的工具。

(1)为了更好的准确性,使用二值图像,寻找Contours之前,先应用阈值化或Canny边缘检测

(2)OpenCV中,找Contours就像从黑色背景中找到白色前景对象,so寻找的目标应当是白色,背景是黑色

# 找Contours
cv2.findContours(src,retrieval mode,approximation method)


# 描绘Contours,能够画出任何形状
cv2.drawContours(src, contours, contour_index, color, thickness)

#Contours存储形状边界的(x,y)坐标

Contour近似法:轮廓是一个形状的边界,具有相同的亮度或颜色。它存储形状边界的(x,y)坐标。但它并非存储boundary所有的坐标,存储哪些坐标是由轮廓近似法规定的。cv2.CHAIN_APPROX_NONE,存储所有边界点;如找到一条直线轮廓。并不需要直线上所有点来表示这条直线,只需要两个端点便可。cv2.CHAIN_APPROX_SIMPLE ,删除所有冗余点进行压缩,节省内存。

2.Contours特征

(1)找出轮廓的不同特征,如面积、周长、质心、边界框等

# 此函数给出计算出的所有moment值的一个字典
M = cv2.moments(counter)

'''
Centroid:
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])

'''
# 计算Contour面积
area = cv2.contourArea(cnt)

# 计算Contour周长
perimeter = cv2.arcLength(contour,isClosed)

# Contour近似
cv2.approxPolyDP(cnt,epsilon,isClosed)

# 检查一条曲线是否凸性的,返回True或False
k = cv2.isContourConvex(cnt)

# 凸壳检测,检查曲线是否存在凸性缺陷,并对其进行纠正
hull = cv2.convexHull(points[, hull[, clockwise[, returnPoints]]
'''
points是传入的Contour
hull是输出,通常省略
clock-wise:方向flag,True时输出的hull为顺时针方向,False时为逆时针
returnPoints:默认True,返回hull point的坐标,False时返回hall point索引
如:returnPoints=True时获得[[[234 202]], [[ 51 202]], [[ 51 79]], [[234 79]]]
    returnPoints=False获得[[129],[ 67],[ 0],[142]].
    而cnt[129] = [[234, 202]]
'''

# 找到Contour的矩形边框
'''
a.正Bounding Rectangle,不考虑Contour目标的旋转,该矩形框面积将不是最小矩形
x,y 表示矩形框的左上角坐标,w,h是宽高
'''
x,y,w,h = cv2.boundingRect(cnt)
img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)

'''
考虑旋转状态,此时的矩形框面积最小,返回一个Box2D结构,包含(x,y,w,h,angle of rotation)
描绘出该矩形框时需要获得四点cv2.boxPoints()
'''
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
im = cv2.drawContours(im,[box],0,(0,0,255),2)

# 找到包围Contour的最小闭环边框
(x,y),radius = cv2.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
img = cv2.circle(img,center,radius,(0,255,0),2)

# 找到包围Contour的内接椭圆边框
ellipse = cv2.fitEllipse(cnt)
im = cv2.ellipse(im,ellipse,(0,255,0),2)

# 拟合一条直线
rows,cols = img.shape[:2]
[vx,vy,x,y] = cv2.fitLine(cnt, cv2.DIST_L2,0,0.01,0.01)
lefty = int((-x*vy/vx) + y)
righty = int(((cols-x)*vy/vx)+y)
img = cv2.line(img,(cols-1,righty),(0,lefty),(0,255,0),2)

3.Contour Properties

(1)目标Contour矩形框的宽高比

x,y,w,h = cv2.boundingRect(cnt)
aspect_ratio = float(w)/h

(2)轮廓面积与矩形包围狂面积比

area = cv2.contourArea(cnt)
x,y,w,h = cv2.boundingRect(cnt)
rect_area = w*h
extent = float(area)/rect_area

(3)Contour面积与凸壳面积之比

area = cv2.contourArea(cnt)
hull = cv2.convexHull(cnt)
hull_area = cv2.contourArea(hull)
solidity = float(area)/hull_area

(4)等效直径是面积与Contour面积相等的圆的直径。

area = cv2.contourArea(cnt)
equi_diameter = np.sqrt(4*area/np.pi)

(5)物体所指向的角度,以下方法也给出了主轴和副主轴的长度。

(x,y),(MA,ma),angle = cv2.fitEllipse(cnt)

(6)掩码和像素点

mask = np.zeros(imgray.shape,np.uint8)
cv2.drawContours(mask,[cnt],0,255,-1)
pixelpoints = np.transpose(np.nonzero(mask))
#pixelpoints = cv2.findNonZero(mask)

(7)最大值、最小值及其位置

min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(imgray,mask = mask)

(8)寻找一个目标的平均color或grayscale模式下的平均intensity

mean_val = cv2.mean(im,mask = mask)

(9)极值点,指object的最上、最下、最右、最左的点。

leftmost = tuple(cnt[cnt[:,:,0].argmin()][0])
rightmost = tuple(cnt[cnt[:,:,0].argmax()][0])
topmost = tuple(cnt[cnt[:,:,1].argmin()][0])
bottommost = tuple(cnt[cnt[:,:,1].argmax()][0])

(10)计算凸性缺陷,目标与凸壳的任何偏差都被当作是一种凸性缺陷

# 为找到凸性缺陷时,在寻找凸壳时将returnPoints设为False
hull = cv2.convexHull(cnt,returnPoints = False)
defects = cv2.convexityDefects(cnt,hull)

# 返回一个数组,每行分别包含--
[start point,end point, farthest point, 
approximate distance to father point]

import cv2
import numpy as np
img = cv2.imread('star.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(img_gray, 127, 255,0)
contours,hierarchy = cv2.findContours(thresh,2,1)
cnt = contours[0]
hull = cv2.convexHull(cnt,returnPoints = False)
defects = cv2.convexityDefects(cnt,hull)
for i in range(defects.shape[0]):
s,e,f,d = defects[i,0]
start = tuple(cnt[s][0])
end = tuple(cnt[e][0])
far = tuple(cnt[f][0])
cv2.line(img,start,end,[0,255,0],2)
cv2.circle(img,far,5,[0,0,255],-1)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

(11)多边形点测试,寻找图像中任一点到一个Contour的最短距离。point位于Contour外时返回值为负,内时为正,位于Contour上一点为0。如下计算点(50,50)到Contour的距离

dist = cv2.pointPolygonTest(cnt,(50,50),True)
# 第三个参数为measureDist
# measureDist为True时,求距离,为False时,求该点是否在contour内部(此时返回+1,-1, 0)
# 若不需要距离时,将measureDist设为False,节省运行时间

(12)形状匹配,cv2.matchShapes() -- 比较两个形状或两个contours并且返回一个相似性度量值,值越小,表示两形状越相像。该计算基于hu-moment值。hu-moment是平移、旋转和尺度不变的七个矩,第七个是斜不变的。可以使用cv2.HuMoments()函数找到这些值。

import cv2
import numpy as np
img1 = cv2.imread('star.jpg',0)
img2 = cv2.imread('star2.jpg',0)
ret, thresh = cv2.threshold(img1, 127, 255,0)
ret, thresh2 = cv2.threshold(img2, 127, 255,0)
contours,hierarchy = cv2.findContours(thresh,2,1)
cnt1 = contours[0]
contours,hierarchy = cv2.findContours(thresh2,2,1)
cnt2 = contours[0]
ret = cv2.matchShapes(cnt1,cnt2,1,0.0)
print ret

'''
结果:
• Matching Image A with itself = 0.0
• Matching Image A with Image B = 0.001946
• Matching Image A with Image C = 0.326911
'''

4.Contour中的层次结构,即亲子关系

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值