目标
在本章中,我们将了解
- 凸性缺陷及其查找方法。
- 求点到多边形的最短距离
- 匹配不同形状
理论与代码
1.凸性缺陷
物体与船体的任何偏差都可视为凸性缺陷。
OpenCV附带了一个现成的功能,cv2.convexityDefects()。基本函数调用如下所示:
hull = cv2.convexHull(cnt,returnPoints = False)
defects = cv2.convexityDefects(cnt,hull)
它返回一个数组,其中每一行包含这些值-[起点、终点、最远点、离最远点的近似距离]。我们可以用图像来可视化它。我们画一条线连接起点和终点,然后在最远的点画一个圆。记住,返回的前三个值是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.点多边形检验
该函数求出图像中的点与轮廓之间的最短距离。当点在等高线外时,返回负距离;当点在内时,返回正距离;如果点在等高线上,则返回零距离。
例如,我们可以检查点(50,50)如下:
dist = cv2.pointPolygonTest(cnt,(50,50),True)
在函数中,第三个参数是measureDist。如果是True的话,找到符号距离。如果是False,它将查找该点是在等高线内还是外部还是在等高线上(分别返回+1、-1、0)。
3.匹配形状
OpenCV附带了一个函数cv2.mediaShapes()这使得我们能够比较两种形状,或者两种等高线,并返回一个显示相似性的度量。结果越低,匹配越好。
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
看,即使是图像旋转对这个比较也没有太大的影响。