OpenCV计算机图像处理 —— 凸性缺陷 + 点多边形测试 + 形状匹配 + 轮廓分层与cv.findContours()

1. 凸性缺陷

``````import cv2 as cv
import numpy as np

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()
``````

2. 点多边形测试

``````import cv2 as cv
import numpy as np
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]
img02 = cv.drawContours(img, [cnt], 0, (0, 0,255), 3)
dist = cv.pointPolygonTest(cnt, (20, 20), True)
dist2 = cv.pointPolygonTest(cnt, (192.5, 156), True)
print("point:(20,20) = " + str(dist))
print("point:(192.5,156) = " + str(dist2))
cv.imshow('test', img02)
cv.waitKey(0)
cv.destroyWindow()
``````

3. 形状匹配

OpenCV中的形状匹配与一个函数有关：cv.matchShapes()，这个函数使我们能够比较两个形状（或两个轮廓），并返回一个显示相似性的度量，这个值越低说明匹配越好，在实质上它是根据矩值计算出来的

``````import cv2 as cv
import numpy as np
from matplotlib import pyplot as pyt

ret, thresh = cv.threshold(img1, 127, 255, 0)
ret, thresh2 = cv.threshold(img2, 127, 255, 0)
ret, thresh3 = cv.threshold(img3, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, 2, 1)
cnt1 = contours[0]
contours, hierarchy = cv.findContours(thresh2, 2, 1)
cnt2 = contours[0]
contours, hierarchy = cv.findContours(thresh3, 2, 1)
cnt3 = contours[0]
ret = cv.matchShapes(cnt1, cnt2, 1, 0.0)
ret2 = cv.matchShapes(cnt1, cnt3, 1, 0.0)
print("星图1与星图2的匹配度量 = " + str(ret))
print("星图1与方图1的匹配度量 = " + str(ret2))
pyt.subplot(1, 3, 1), pyt.imshow(img1, cmap="gray")
pyt.title("star_img01"), pyt.xticks([]), pyt.yticks([])
pyt.subplot(1, 3, 2), pyt.imshow(img2, cmap="gray")
pyt.title("star_img02"), pyt.xticks([]), pyt.yticks([])
pyt.subplot(1, 3, 3), pyt.imshow(img3, cmap="gray")
pyt.title("rectangle_img01"), pyt.xticks([]), pyt.yticks([])
pyt.show()
``````

4. 轮廓分层与cv.findContours()

4.2 轮廓检索模式（四种参数）

RETR_LIST

RETR_EXTERNAL

RETR_CCOMP

RETR_TREE

``````import cv2 as cv
import numpy as np
from matplotlib import pyplot as pyt

img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(img_gray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_LIST, cv.CHAIN_APPROX_NONE)
cnt = contours[0]
contours, hierarchy = cv.findContours(thresh, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)
cnt2 = contours[0]
contours, hierarchy = cv.findContours(thresh, cv.RETR_CCOMP, cv.CHAIN_APPROX_NONE)
cnt3 = contours[0]
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
cnt4 = contours[0]
img1 = cv.drawContours(thresh, [cnt], 0, (255, 0, 0), 2)
img2 = cv.drawContours(thresh, [cnt2], 0, (0, 255, 0), 2)
img3 = cv.drawContours(thresh, [cnt3], 0, (0, 0, 255), 2)
img4 = cv.drawContours(thresh, [cnt4], 0, (0, 0, 0), 2)
pyt.subplot(2, 2, 1), pyt.imshow(img1, cmap="gray")
pyt.title("RETR_LIST"), pyt.xticks([]), pyt.yticks([])
pyt.subplot(2, 2, 2), pyt.imshow(img2, cmap="gray")
pyt.title("RETR_EXTERNAL"), pyt.xticks([]), pyt.yticks([])
pyt.subplot(2, 2, 3), pyt.imshow(img3, cmap="gray")
pyt.title("RETR_CCOMP"), pyt.xticks([]), pyt.yticks([])
pyt.subplot(2, 2, 4), pyt.imshow(img3, cmap="gray")
pyt.title("RETR_TREE"), pyt.xticks([]), pyt.yticks([])
pyt.show()
``````

（注：文章内容参考OpenCV4.1中文官方文档）

THE END