OpenCV-Python获取凸包与凸缺陷详解

小满
小满
发布时间:2026-10-15| 5人浏览过
原创

本文介绍OpenCV-Python中获取图像轮廓凸包的方法,详解cv2.convexHull()函数的参数与返回值。通过实例演示如何绘制凸包多边形,并进一步讲解利用cv2.convexityDefects()计算凸缺陷的步骤。最后结合手势识别案例,展示二值化阈值调整与凸包点集筛选的实际应用,帮助读者掌握轮廓几何分析技巧。

前言

逼近多边形是对图像轮廓的高度近似,而凸包的概念旨在简化这种逼近多边形。凸包与逼近多边形类似,但它特指物体最外层的“凸”多边形结构。

简而言之,凸包是指完全包含原有轮廓,且仅由轮廓上的点构成的多边形。其核心特征是处处为凸,即连接凸包内任意两点的直线段均位于凸包内部,且任意连续三个点形成的内角均小于180度。

在OpenCV库中,提供了cv2.convexHull()函数用于获取轮廓的凸包。该函数的完整定义如下:


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

points:表示输入的轮廓数据。

hull:函数的返回值,即凸包的角点坐标。可以理解为多边形的顶点坐标或其在原轮廓中的索引。

clockwise:布尔类型参数。当设置为True时,返回的凸包角点按顺时针方向排列;若为False,则按逆时针方向排列。

returnPoints:布尔类型参数,默认值为True。当为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)

此处我们选取了一张图像,并计算其凸包角点。运行程序后,输出的角点坐标如下:

若将参数returnPoints修改为False,程序将返回对应的6个索引值。

在此基础上,只需添加一行代码即可绘制出凸包多边形,具体添加的代码如下:


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

运行上述代码后,显示效果如下:

凸缺陷

凸包与原始轮廓之间的区域被称为凸缺陷。在OpenCV中,可以使用cv2.convexityDefects()函数来获取这些凸缺陷,其完整定义如下:


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

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

运行程序后,效果如下:


如上图所示,图中用点标记出了凸缺陷位置。可以看到,五角星的每个凹肩部分均被识别为凸缺陷。

最后进行扩展说明,OpenCV还提供了cv2.isContourConvex()函数用于判断轮廓是否为凸形。同时,cv2.pointPolygonTest()函数可用于计算点到多边形(或轮廓)的最短距离(即垂线距离),这属于点与多边形关系测试的范畴。感兴趣的读者可自行实验这两个函数。

简单例子 手势图片

接下来,我们将介绍一张难度稍高的图像——手势图片(finger.jpg),图像如下所示:

我们将对该手势图像进行凸包检测。基本处理思路与前文一致,但在二值化阈值设定及凸包点集大小的筛选上需做调整。此处设定二值化阈值为235,并仅保留凸包点集中点数大于5的情况。完整的Python代码如下:


import cv2

# 读取图片并转至灰度模式
imagepath = 'F://finger.jpg'
img = cv2.imread(imagepath, 1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化,取阈值为235
ret, thresh = cv2.threshold(gray, 235, 255, cv2.THRESH_BINARY)

# 寻找图像中的轮廓
image, contours, hierarchy = cv2.findContours(thresh, 2, 1)

# 寻找物体的凸包并绘制凸包的轮廓
for cnt in contours:
    hull = cv2.convexHull(cnt)
    length = len(hull)
    # 如果凸包点集中的点个数大于5
    if length > 5:
        # 绘制图像凸包的轮廓
        for i in range(length):
            cv2.line(img, tuple(hull[i][0]), tuple(hull[(i+1)%length][0]), (0,0,255), 2)

cv2.imshow('finger', img)
cv2.waitKey()

检测到的凸包结果如下图所示:

从结果可以看出,共检测到2个凸包:一个是包围整个手势外围的大凸包,另一个是由两个手指形成的内部图形(形似字母O)的小凸包,这符合我们的预期结果。

到此这篇关于OpenCV-Python实现凸包的获取的文章就介绍到这了,更多相关OpenCV-Python 凸包内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。