OpenCV Python 轮廓
【目标】
- 凸性缺陷查找
 - 点与多边形的关系
 - 不同形状的匹配
 
【代码】

左图中红色点为凸性检测的缺陷点,即凹点
右图为了验证点与多边形关系而做的图,也是官网要求做的练习。
import cv2 
import numpy as np 
img = cv2.imread('star.png', 0)
colorimg = cv2.imread('star.png', 1)
convexHullImg = colorimg.copy()
ret, thresh = cv2.threshold(img, 128, 255, cv2.THRESH_BINARY)
# 寻找轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]
# 凸包
hull = cv2.convexHull(cnt, returnPoints=False)
defects = cv2.convexityDefects(cnt, hull)
# 画出缺陷凹点
for i in range(defects.shape[0]):
    startptidx, endptidx, farptidx, dis = defects[i, 0]
    startpt = tuple(cnt[startptidx][0])
    endpt = tuple(cnt[endptidx][0])
    farpt = tuple(cnt[farptidx][0])    
    cv2.line(convexHullImg, startpt, endpt, (0, 255, 255))
    cv2.circle(convexHullImg, farpt, 3, (0, 0, 255), 3)
# 根据点在图像中和轮廓中的位置,画出颜色图
polygonTestImg = colorimg.copy()
# cv2.circle(polygonTestImg, (280, 180), 3, (0, 0, 255), 3)
dist = cv2.pointPolygonTest(cnt, (50, 50), True)
h, w, _ = polygonTestImg.shape
# 在轮廓上,为白色
bluevalue = 255
redvalue = 255
for j in range(h):
    for i in range(w):
        dist = cv2.pointPolygonTest(cnt, (i, j), True)
        if dist > 127:
            dist = 127
        
        if dist < -127:
            dist = -127
        
        if dist > 0:
            colorshow = (255 - dist * 2, 255 - dist * 2, 0)
        elif dist < 0:
            colorshow = (0, 255 + dist * 2, 255 + dist * 2)
        elif dist == 0:
            colorshow = (255, 255, 255)
        
        cv2.circle(polygonTestImg, (i, j), 2, colorshow, 2)
cv2.imshow('convexHullImg', convexHullImg)
cv2.imshow('polygonTestImg', polygonTestImg)
cv2.waitKey(0)
cv2.destroyAllWindows()
 

# 测试形状匹配
import cv2
import numpy as np 
img1 = cv2.imread('star.png', 0)
img2 = cv2.imread('box.png', 0)
img3 = cv2.imread('testfit.png', 0)
ret1, thresh1 = cv2.threshold(img1, 127, 255, cv2.THRESH_BINARY)
ret2, thresh2 = cv2.threshold(img2, 127, 255, cv2.THRESH_BINARY)
ret3, thresh3 = cv2.threshold(img3, 127, 255, cv2.THRESH_BINARY)
con1, hir1 = cv2.findContours(thresh1, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
con2, hir2 = cv2.findContours(thresh2, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
con3, hir3 = cv2.findContours(thresh3, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnt1 = con1[0]
cnt2 = con2[0]
cnt3 = con3[0]
ret12 = cv2.matchShapes(cnt1, cnt2, cv2.CONTOURS_MATCH_I2, 0.0) 
ret13 = cv2.matchShapes(cnt1, cnt3, cv2.CONTOURS_MATCH_I2, 0.0)
ret23 = cv2.matchShapes(cnt2, cnt3, cv2.CONTOURS_MATCH_I2, 0.0)
print(ret12, ret13, ret23)
cv2.imshow('img1', img1)
cv2.imshow('img2', img2)
cv2.imshow('img3', img3)
cv2.waitKey(0)
cv2.destroyAllWindows()
 
输出结果如下:
0.05888818307213595 0.2987404256696341 1.6190198650037022
 
【接口】
- convexityDefects
 
void cv::convexityDefects	(	InputArray 	contour,
InputArray 	convexhull,
OutputArray 	convexityDefects 
);
 
cv2.convexityDefects(	contour, convexhull[, convexityDefects]	) ->	convexityDefects
 
计算查找一个轮廓的凸性缺陷
- contour: 输入的轮廓
 - convexhull: 轮廓的凸包,用
 convexHull- convexityDefects: 凸性缺陷输出向量, 每个缺陷是 4个整型元素的 vector。
 
- pointPolygonTest
 
double cv::pointPolygonTest	(	InputArray 	contour,
Point2f 	pt,
bool 	measureDist 
);
 
cv2.pointPolygonTest(	contour, pt, measureDist	) ->	retval
 
判断一个点是否在轮廓内或边缘上,计算其距离;正数在内部,负数在外部;
如果measureDist=false则返回1, -1, 0
- contour: 输入的轮廓
 - pt: 测试点
 - measureDist: 如果为真,则计算距离,否则不用计算,只判断是否在内部还是外部;
 
- matchShapes
 
double cv::matchShapes	(	InputArray 	contour1,
InputArray 	contour2,
int 	method,
double 	parameter 
);
 
cv2.matchShapes(	contour1, contour2, method, parameter	) ->	retval
 
比较两个形状
- contour1: 第一个轮廓
 - contour2: 第二个轮廓
 - method: 比较的方法 见下 ShapeMatchModes
 - parameter: 方法的特殊参数(暂时不支持)
 
- ShapeMatchModes
 

【参考】
- OpenCV官方文档
 
















![[附源码]SSM计算机毕业设计江苏人才信息管理系统JAVA](https://img-blog.csdnimg.cn/1c7fc8ec1c0e407b9236562bf2abbe7f.png)

