python opencv入门 更多关于轮廓的函数(20)

内容来自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()

python opencv入门 更多关于轮廓的函数(20)_第1张图片

查找凸缺陷时的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()

你可能感兴趣的:(python opencv入门 更多关于轮廓的函数(20))