内容来自OpenCV-Python Tutorials 自己翻译整理
目标 如何找到凸缺陷 某一点到多边形的最短距离 不同形状匹配
凸缺陷
在目标图形上的任何凹陷都可以被看作凸缺陷,在Opencv中有cv2.convexityDefects()函数可以找到凸缺陷。
import cv2 import numpy as np img = cv2.imread('11.jpg') img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(img_gray, 127, 255,0) im,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()查找凸缺陷时的hull要用参数returnPoints = False defects 为一个数组,每行包含[起点,终点,最远点,到最远点的近似距离] 起点和终点用绿线连接,最远点画个红圈。 返回值的值是轮廓的索引
点与多边形测试 求解图像一个点到一个目标轮廓的最短距离,点在轮廓外部返回负值,在轮廓上返回0,轮廓内部返回正值。
import cv2 import numpy as np img = cv2.imread('11.jpg') img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(img_gray, 127, 255,0) im,contours,hierarchy = cv2.findContours(thresh,2,1) cnt = contours[0] dist = cv2.pointPolygonTest(cnt,(50,50),True) print(dist)pointPolygonTest函数的第三个参数是measureDist设置为 True会计算最 短距离,如果是 False,只会判断这个点与轮廓之间的位置关系(返回值为 +1,-1,0)。 如果不知道具体距离,建议将第三个参数设置为False,速度回提升2至3倍
形状匹配 cv2.matchShape可以比较两个轮廓的相似程度,返回值越小,越匹配。 计算方法根据Hu矩计算
(此处比较同一个图片中的两个轮廓)
import cv2 import numpy as np img = cv2.imread('11.jpg') img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(img_gray, 127, 255,0) im,contours,hierarchy = cv2.findContours(thresh,2,1) cnt1 = contours[0] cnt2 = contours[1] ret = cv2.matchShapes(cnt1,cnt2,1,0.0) print(ret)图形发生旋转以后,对匹配结果影响不大,这里涉及到Hu矩的原理。
练习: 在图片上绘制不同颜色的点,根据点到轮廓的距离来决定。
import cv2 import numpy as np def draw_circle(event,x,y,flags,param): if event == cv2.EVENT_LBUTTONDBLCLK: dist = cv2.pointPolygonTest(cnt,(x,y),True) if dist > 0: cv2.circle(img,(x,y),4,(255,0,0),-1) elif dist==0: cv2.circle(img,(x,y),4,(0,255,0),-1) elif dist < 0: cv2.circle(img,(x,y),4,(0,0,255),-1) img = cv2.imread('11.jpg') img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(img_gray, 127, 255,0) im,contours,hierarchy = cv2.findContours(thresh,2,1) cnt = contours[0] cv2.namedWindow('image') cv2.setMouseCallback('image',draw_circle) while(1): cv2.imshow('image',img) if cv2.waitKey(20) & 0xFF == 27: break cv2.destroyAllWindows()