图像轮廊二
凸包
逼近多边形是轮廊的高度相似,但是有时候,我们希望使用一个多边形的凸包来简化它,凸包跟逼近多边形很相似,只不过它是物体最外层的“凸”多边形。凸包指的是完全包含原有轮廊,并且仅有轮廊上的点所构成的多边形。凸包的每一处都是凸的,即在凸包内连接任意两点的直线都在凸包的内部。在凸包内,任意连接三个点的内角小于180°
1.使用cv2.convexHull()函数,实现图像轮廓凸包的获取。
2.使用cv2.polylines()函数,实现图像轮廓凸包的绘制。
凸包的绘制
cv2.polylines(src, [points], isClosed,color, thickness)
src:要处理的图像。
points:点集。
isClosed:布尔型,True表示的是线段闭合,False表示的是仅保留线段。
color:线段颜色,格式是(B,G,R)值。
thickness:数值型,厚度,默认值为1,如果对封闭图形,正方形,三角形等传入-1,则会填充整个图形。
import cv2
img = cv2.imread('contours2.png', 1)
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_NONE)
cnt = contours[0]
hull = cv2.convexHull(cnt)
cv2.polylines(img,[hull],True,(255,0,0),2)
cv2.imshow('line', img)
cv2.waitKey()
cv2.destroyAllWindows()
实物凸包检测
import cv2
img = cv2.imread('hand.png', 1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 60, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE)
n=len(contours)
contoursImg=[]
x=0
for i in range(n):
area = cv2.contourArea(contours[i])
if area>10000:
print(f"轮廓{i}的面积:\n{area}")
x=i
cnt = contours[x]
cv2.imshow("binary",binary)
hull = cv2.convexHull(cnt)
cv2.polylines(img,[hull],True,(0,255,0),2)
cv2.drawContours(img,contours,x,(0,0,255), 3)
#显示图片
cv2.imshow('line', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
凸缺陷的概念
凸包与轮廓之间的部分,称为凸缺陷。轮廓上距离这条线最远的
点就是凸缺陷的点。
convexityDefects = cv2.convexityDefects(contour, convexhull)
contour:轮廓。
convexhull:凸包.
import cv2
o = cv2.imread('contours2.png')
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
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(o,start,end,[0,0,255],2)
cv2.circle(o,far,5,[255,0,0],-1)
cv2.imshow('result',o)
cv2.waitKey(0)
cv2.destroyAllWindows(