凸包---OpenCV-Python开发指南(28)

举报
择城终老 发表于 2021/07/26 23:40:28 2021/07/26
【摘要】 目录 前言获取凸包角点凸缺陷 前言 逼近多边形是某个图像轮廓的高度近似,而凸包的提出是为了简化逼近多边形的。其实,凸包跟逼近多边形很像,只不过它是物体最外层的“凸”多边形。 简单的概括,凸包是指完全包含原有轮廓,并且仅由轮廓上的点所构成的多边形。凸包的特点是每一处都是凸的,即在凸包内连接任意两点的直线都在凸包的内部,并且任意连续3个点的内角小于180度...

前言

逼近多边形是某个图像轮廓的高度近似,而凸包的提出是为了简化逼近多边形的。其实,凸包跟逼近多边形很像,只不过它是物体最外层的“凸”多边形。

简单的概括,凸包是指完全包含原有轮廓,并且仅由轮廓上的点所构成的多边形。凸包的特点是每一处都是凸的,即在凸包内连接任意两点的直线都在凸包的内部,并且任意连续3个点的内角小于180度。

在OpenCV中,它给我们提供cv2.convexHull()来获取轮廓的凸包。其完整定义如下:

def convexHull(points, hull=None, clockwise=None, returnPoints=None): 

  
 
  • 1

points:轮廓

hull:返回值,为凸包角点。可以理解为多边形的点坐标,或索引。

clockwise:布尔类型,为True时,凸包角点将按顺时针方向排列;为False时,为逆时针。

returnPoints:布尔类型,默认值True,函数返回凸包角点的x/y坐标;为False时,函数返回轮廓中凸包角点的索引。

获取凸包角点

既然,我们已经了解了凸包的作用,并且理解了OpenCV提供的函数。下面,我们随便选取一张图,获取凸包角点。具体代码如下所示:

import cv2

img = cv2.imread("24.jpg")

cv2.imshow("img", img)
# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

hull=cv2.convexHull(contours[0])

print(hull)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

这里,我们随便获取了一张图像,并获取其凸包的角点。运行之后,角点坐标如下:

凸包角点

如果修改参数returnPoints为False,会返回对应的6个索引值。

这里我们再添加一行代码就可以绘制凸包多边形了,具体添加的代码如下:

#获取hull之后
cv2.polylines(img, [hull], True, (0, 255, 0), 2)
cv2.imshow("img1", img)

  
 
  • 1
  • 2
  • 3

运行之后,效果如下所示:
凸包效果

凸缺陷

凸包与轮廓之间的部分我们称之为凸缺陷。在OpenCV中使用函数cv2.convexityDefects()获取凸缺陷,其完整定义如下:

def convexityDefects(contour, convexhull, convexityDefects=None): 

  
 
  • 1

contour:轮廓

convexhull:凸包

convexityDefects:返回值,为凸缺陷点集。它是一个数组,返回的指包括[起点,终点,轮廓上的距离凸包最远点,最远点到凸包的近似距离]

特别注意,用该函数计算凸缺陷之前,我们需要使用函数cv2.convexHull()获取凸包,但其参数returnPoints必须为False。

下面,我们来使用该函数计算上图的凸缺陷。代码如下:

import cv2

img = cv2.imread("24.jpg")
cv2.imshow("img", img)

# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

hull = cv2.convexHull(contours[0], returnPoints=False)

defects = cv2.convexityDefects(contours[0], hull)
print(defects)

for i in range(defects.shape[0]): s, e, f, d = defects[i, 0] start = tuple(contours[0][s][0]) end = tuple(contours[0][e][0]) far = tuple(contours[0][f][0]) cv2.line(img, start, end, [0, 255, 0], 2) cv2.circle(img, far, 5, [0, 0, 255], -1)

cv2.imshow("img1", img)

cv2.waitKey()
cv2.destroyAllWindows()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

运行之后,效果如下:

控制台与图像
如上图所示,我们用点标记出来的凸缺陷,可以看到五角星的每个凹肩都是凸缺陷。

最后可以扩展以下,其中OpenCV提供函数cv2.isContourConvex()来判断轮廓是否是凸形的。同时,也提供了cv2.pointPolygonTest()函数来计算点到多边形(轮廓)的最短距离,也就是垂线距离,这个计算由称为点和多边形的关系测试。感兴趣的读者可以自己实验这两个方函数。

文章来源: liyuanjinglyj.blog.csdn.net,作者:李元静,版权归原作者所有,如需转载,请联系作者。

原文链接:liyuanjinglyj.blog.csdn.net/article/details/113934545

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。