zl程序教程

您现在的位置是:首页 >  后端

当前栏目

【OpenCV-Python】教程:3-9 轮廓(4)更多函数

PythonOpencv教程 函数 轮廓
2023-09-14 09:01:40 时间

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-Python】教程:3-9 轮廓(1)开始
【OpenCV-Python】教程:3-9 轮廓(2)轮廓特征
【OpenCV-Python】教程:3-9 轮廓(3)轮廓属性

【参考】

  1. OpenCV官方文档