2019-7-29 opencv图像处理9-轮廓4(Contours)更多函数(凸缺陷/点至多边形测试/图形匹配-hu矩)

官网参见https://docs.opencv.org/3.4.1/d5/d45/tutorial_py_contours_more_functions.html

1.凸缺陷

我们已经了解过凸包概念https://blog.csdn.net/weixin_42555985/article/details/97115338。
物体和凸包之间的任何偏差就称为凸缺陷。
opencv提供cv.convexityDefects()函数找到凸缺陷。
调用方式如下:

hull = cv.convexHull(cnt,returnPoints = False)
defects = cv.convexityDefects(cnt,hull)

cv.convexHull()函数获取凸包,其中cnt是利用cv2.findContours()函数获取的轮廓。
cv.convexityDefects()函数就是把cnt轮廓和hull凸包进行比较,获得凸缺陷。

为了找到凸缺陷,convexHull()函数必须传入returnPoints = False

函数返回一个数组,每一行包含的值是:起始点,终点,最远的点,最远点的近似距离。我们可以在图像中显示它。起点和终点画一根直线,然后在最远的点画个圆。
注意:返回值是轮廓的索引点,可以在cnt中找到对应的值。

例,找到凸缺陷

# -*- coding: cp936 -*-
import cv2 
import numpy as np
from matplotlib import pyplot as plt


img = cv2.imread('defects.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(img_gray, 127, 255,0)
im2,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()

2019-7-29 opencv图像处理9-轮廓4(Contours)更多函数(凸缺陷/点至多边形测试/图形匹配-hu矩)_第1张图片
结果如上。

2.点至多边形测试(Point Polygon Test)

这个函数用于找到图像中的点到轮廓的最短距离。
如果返回负值,表示点在轮廓外部;如果是正值,表示点在轮廓内部;0,表示在轮廓上。
假设我们要检查点(50,50)的距离

dist = cv.pointPolygonTest(cnt,(50,50),True)

函数的第三个参数measureDist,如果是True,表示计算最短距离;如果是False,表示判断点和轮廓的位置关系,返回1,-1,0。

如果不需要知道距离,可以把这个参数设置为False。这样可以解决计算速度,大约可以提高2-3倍。

3.形状匹配
opencv提供 cv.matchShapes() 函数来对比2个图形或者轮廓,并返回相似度。返回值越小,表示越相似。它是基于**hu矩(hu-moment)**值来计算的。
例1,测试形状匹配-自己匹配自己

import cv2 
import numpy as np
from matplotlib import pyplot as plt


img = cv2.imread('defects.jpg',0)
img2 = cv2.imread('defects.jpg',0)

ret, thresh = cv2.threshold(img, 127, 255,0)
ret, thresh2 = cv2.threshold(img2, 127, 255,0)

im,contours,hierarchy = cv2.findContours(thresh,2,1)
cnt1 = contours[0]
im2,contours2,hierarchy = cv2.findContours(thresh2,2,1)
cnt2 = contours2[0]

ret = cv2.matchShapes(cnt1,cnt2,1,0.0)
print ret 

2019-7-29 opencv图像处理9-轮廓4(Contours)更多函数(凸缺陷/点至多边形测试/图形匹配-hu矩)_第2张图片
我们导入上面图像,然后自己和自己匹配,结果为0.0,显然是完全匹配的。

例2,测试形状匹配–近似图形
这次我们尝试把下面心形和上面那个图匹配。
2019-7-29 opencv图像处理9-轮廓4(Contours)更多函数(凸缺陷/点至多边形测试/图形匹配-hu矩)_第3张图片

import cv2 
import numpy as np
from matplotlib import pyplot as plt


img = cv2.imread('defects.jpg',0)
img2 = cv2.imread('7.jpg',0)

ret, thresh = cv2.threshold(img, 127, 255,0)
ret, thresh2 = cv2.threshold(img2, 127, 255,0)

im,contours,hierarchy = cv2.findContours(thresh,2,1)
cnt1 = contours[0]
im2,contours2,hierarchy = cv2.findContours(thresh2,2,1)
cnt2 = contours2[0]

ret = cv2.matchShapes(cnt1,cnt2,1,0.0)
print ret 

结果为0.00726087928139

例3,测试形状匹配–差别很大图形
这次我们尝试把下面矩形和例1的那个图心形匹配。
2019-7-29 opencv图像处理9-轮廓4(Contours)更多函数(凸缺陷/点至多边形测试/图形匹配-hu矩)_第4张图片

import cv2 
import numpy as np
from matplotlib import pyplot as plt


img = cv2.imread('defects.jpg',0)
img2 = cv2.imread('8.jpg',0)

ret, thresh = cv2.threshold(img, 127, 255,0)
ret, thresh2 = cv2.threshold(img2, 127, 255,0)

im,contours,hierarchy = cv2.findContours(thresh,2,1)
cnt1 = contours[0]
im2,contours2,hierarchy = cv2.findContours(thresh2,2,1)
cnt2 = contours2[0]

ret = cv2.matchShapes(cnt1,cnt2,1,0.0)

print ret

结果0.330222004794,明显比2个心形之间比较差多了。
同时还可以发现,例1和例2的2个心形之间匹配,没有因为例2的图形发生的旋转而降低。

4.什么是hu矩(hu-moment)

对于形状匹配来说,我们希望计算出来的矩具有平移不变性,旋转不变性,尺度不变性,hu矩就可以满足这一要求。
hu矩是7个数字的组合,每个数字都是利用central moments计算得来,前6个被证明包含平移不变性,旋转不变性,尺度不变性和翻转不变性,第7个的符号与图像翻转有关(如果一个形状是另一个的镜像图像,那么他们的hu矩中第七个数字相同,符号是相反的)。
opencv中提供cv.HuMoments()函数来获得hu矩。

你可能感兴趣的:(IT,opencv)