IT|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 pltimg = 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()

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

结果如上。
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 pltimg = 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

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

我们导入上面图像,然后自己和自己匹配,结果为0.0,显然是完全匹配的。
例2,测试形状匹配–近似图形
这次我们尝试把下面心形和上面那个图匹配。
IT|2019-7-29 opencv图像处理9-轮廓4(Contours)更多函数(凸缺陷/点至多边形测试/图形匹配-hu矩)
文章图片

import cv2 import numpy as np from matplotlib import pyplot as pltimg = 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的那个图心形匹配。
IT|2019-7-29 opencv图像处理9-轮廓4(Contours)更多函数(凸缺陷/点至多边形测试/图形匹配-hu矩)
文章图片

import cv2 import numpy as np from matplotlib import pyplot as pltimg = 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) 【IT|2019-7-29 opencv图像处理9-轮廓4(Contours)更多函数(凸缺陷/点至多边形测试/图形匹配-hu矩)】对于形状匹配来说,我们希望计算出来的矩具有平移不变性,旋转不变性,尺度不变性,hu矩就可以满足这一要求。
hu矩是7个数字的组合,每个数字都是利用central moments计算得来,前6个被证明包含平移不变性,旋转不变性,尺度不变性和翻转不变性,第7个的符号与图像翻转有关(如果一个形状是另一个的镜像图像,那么他们的hu矩中第七个数字相同,符号是相反的)。
opencv中提供cv.HuMoments()函数来获得hu矩。

    推荐阅读