理论和代码
1.凸面缺陷
OpenCV提供了现成的函数来做这个,cv2.convexityDefects().
hull=cv2.convexHull(cnt,returnPoints=False)
defects=cv2.convexityDefects(cnt,hull)
注意:
我们要传returnPoints = False来找凸形外壳。
它返回了一个数组,每行包含这些值:[start point, end point, farthest point, approximate distance to farthest point].我们可以用图像来显示他们。我们画根线把start point和end point连起来。然后画一个圆在最远点。记住最前三个返回值是cnt的索引,所以我们我们得从cnt里拿出这些值
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()
结果:
2.Point Polygon Test
这个函数找到图像里的点和轮廓之间的最短距离。它返回的距离当点在轮廓外的时候是负值,当点在轮廓内是正值,如果在轮廓上是0
比如,我们可以检查(50, 50)这个点:
dist=cv2.pointPolygonTest(cnt,(50,50),True)
在这个函数里,第三个参数是measureDist, 如果为True,是找带符号的距离。如果为False,会找点是否在内,外,或轮廓上(会相应返回+1, -1, 0)
注意:
如果你不想找距离,确保第三个参数是False,因为,这是个耗时的处理。所以,用False会得到2-3倍的提速
3.匹配形状
OpenCV提供一个函数cv2.matchShapes()来让我们可以比较两个形状,或者两个轮廓来返回一个量表示相似度。结果越低,越相似,它是根据hu矩来计算的。不同的计算方法在文档里有介绍。
import cv2
import numpy as npimg1 = 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
尝试匹配一下图形:
得到的结果如下:
·用图形A和自己比较,得到0.0
·用图形A和B匹配,得到0.001946
·用A匹配C = 0.326911