翻译及二次校对:cvtutorials.com
目标
在本章中,我们将了解到:
- 1. 凸性缺陷以及如何找到它们。
- 2. 寻找从一个点到一个多边形的最短距离
- 3. 匹配不同的形状
理论和代码
- 1. 凸性缺陷
我们在关于轮廓的内容中看到了什么是凸面体。任何偏离这个凸包的物体都可以被认为是凸性缺陷。
OpenCV提供了一个现成的函数来寻找这个缺陷,即cv.convexityDefects()。一个基本的函数调用看起来如下。
代码语言:javascript复制hull = cv.convexHull(cnt,returnPoints = False)
defects = cv.convexityDefects(cnt,hull)
注意:请记住,我们在寻找凸面体时必须传递returnPoints = False,以便找到凸性缺陷。
它返回一个数组,每一行都包含这些值 - [ 起始点,终点,最远点,到最远点的大致距离 ]。我们可以用一个图像将其可视化。我们画一条连接起点和终点的线,然后在最远点画一个圆。请记住,前三个返回值是cnt的索引。所以我们必须从cnt中获取这些值。
代码语言:javascript复制import cv2 as cv
import numpy as np
img = cv.imread('star.jpg')
img_gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,thresh = cv.threshold(img_gray, 127, 255,0)
contours,hierarchy = cv.findContours(thresh,2,1)
cnt = contours[0]
hull = cv.convexHull(cnt,returnPoints = False)
defects = cv.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])
cv.line(img,start,end,[0,255,0],2)
cv.circle(img,far,5,[0,0,255],-1)
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()
然后看看结果:
- 1. 点多边形测试
这个函数找出图像中的一个点和一个轮廓线之间的最短距离。它返回的距离是:当点在轮廓线外时为负数,当点在轮廓线内时为正数,如果点在轮廓线上则为零。
例如,我们可以检查点(50,50),如下所示。
代码语言:javascript复制dist = cv.pointPolygonTest(cnt,(50,50),True)
在这个函数中,第三个参数是measureDist,如果它是True,它找到有符号的距离。如果是False,它将发现该点是在轮廓线内还是在轮廓线外或在轮廓线上(它分别返回 1、-1、0)。
注意:如果你不想找距离,确保第三个参数是False,因为这是一个耗时的过程。所以,把它设为假值可以使速度提高2-3倍。
- 1. 匹配形状
OpenCV有一个函数cv.matchShapes(),它使我们能够比较两个形状,或两个轮廓,并返回一个显示相似度的指标。结果越低,说明它的匹配度越高。它是根据hu-moment值来计算的。文档中解释了不同的测量方法。
代码语言:javascript复制import cv2 as cv
import numpy as np
img1 = cv.imread('star.jpg',0)
img2 = cv.imread('star2.jpg',0)
ret, thresh = cv.threshold(img1, 127, 255,0)
ret, thresh2 = cv.threshold(img2, 127, 255,0)
contours,hierarchy = cv.findContours(thresh,2,1)
cnt1 = contours[0]
contours,hierarchy = cv.findContours(thresh2,2,1)
cnt2 = contours[0]
ret = cv.matchShapes(cnt1,cnt2,1,0.0)
print( ret )
我试着用下面给出的不同形状来匹配形状。
得到了以下结果:
- • 匹配图像A与自身=0.0
- • 图像A与图像B的匹配=0.001946
- • 图片A与图片C的匹配度=0.326911
看,即使是图像旋转也不会对这个比较产生什么影响。
注意:Hu-Moments是七个对平移、旋转和缩放不变的矩。第七个是歪斜不变的。这些值可以通过cv.HuMoments()函数找到。
练习
- 1. 查看cv.pointPolygonTest()的文档,你可以找到一个红蓝相间的漂亮图像。它代表了所有像素到上面的白色曲线的距离。曲线内的所有像素都是蓝色的,这取决于距离。同样地,外面的点是红色的。轮廓线的边缘用白色标记。所以问题很简单。写一段代码来创建这样的距离表示。
- 2. 用cv.matchShapes()比较数字或字母的图像。( 这将是走向OCR的一个简单步骤)