OpenCV凸包检测与凸缺陷详解:原理、API与Python实现

听雨眠
听雨眠
发布时间:2026-10-16 | 5人浏览过
原创

本文详解OpenCV中凸包检测与凸缺陷提取的原理及实现。重点解析cv2.convexHull和cv2.convexityDefects函数的参数设置,特别是returnPoints为False时的索引返回机制。通过Python代码示例展示如何绘制轮廓、凸包及缺陷点,并说明其在物体识别与手势识别中的应用。

1、凸包检测与凸缺陷定义

凸包是指将点集中最外围的点依次连接所形成的凸多边形,该多边形能够完全包含点集中的所有点。在计算机视觉领域,物体凸包检测技术广泛应用于物体识别、手势识别以及边界检测等场景。

凸包检测通常作为轮廓分析的后续步骤。在对二值图像进行轮廓分析后,可以构建每个轮廓对应的凸包,系统会返回构成该凸包的点集。利用这些返回的点集,即可在图像中绘制出对应轮廓的凸包。一般而言,凸性曲线表现为向外凸起或保持平直;若曲线出现向内凹陷的部分,则被称为凸性缺陷。

下图直观展示了凸包与凸缺陷的定义:

2、opencv相关实现函数

OpenCV库提供了两个关键函数:convexHull用于执行物体轮廓的凸包检测,而convexityDefects则用于检测凸缺陷。首先需明确各函数的参数含义:

hull = cv2.convexHull(points, clockwise, returnpoints)

各参数意义:

points:输入轮廓的点集数据。

clockwise:方向标志位。若设为True,输出的凸包顶点按顺时针方向排列;若为False,则按逆时针方向排列。

returnPoints:布尔值,决定输出格式。若为True,返回凸包的顶点坐标点集;若为False,返回与凸包顶点对应的原轮廓点的索引值。

hull:输出参数,表示检测到的凸包结果。当returnPoints为True时,返回的是凸包的顶点坐标点集;当returnPoints为False时,返回的是与原凸包顶点对应的轮廓点索引。

以下函数用于查找凸缺陷:

convexityDefects = cv2.convexityDefect(contour, convexhull)

注意:

在进行凸缺陷检测时,必须将凸包检测函数中的returnPoints参数设置为False。

凸缺陷检测结果为一个数组,每一行包含四个值:起点索引、终点索引、最远点索引以及到最远点的近似距离。前三个值均为轮廓点的索引。

contour:待检测的轮廓数据,可通过调用findContours函数获取。

convexhull:检测到的凸包数据,可通过调用convexHull函数获取。

convexityDefects:输出参数,即检测的最终结果。返回一个数组,其中每一行包含[起点索引,终点索引,最远点索引,到最远点的近似距离]。前三个值均为轮廓索引。

前三个值的含义分别为:凸缺陷的起始点索引、凸缺陷的终点索引、凸缺陷的最深点索引(即边缘点到凸包距离最大的点)。

3、代码实践

我们可以在同一张图像上同时显示轮廓的凸包和凸缺陷。

我们将起点和终点用一条红线连接,并在最远点处绘制一个蓝色圆圈。需要注意的是,返回结果的前三个值是轮廓点的索引,因此我们需要从原始轮廓点数据中查找这些具体的坐标点。

前三个值的含义分别为:凸缺陷的起始点索引、凸缺陷的终点索引、凸缺陷的最深点索引(即边缘点到凸包距离最大的点)。

凸包检测和凸缺陷检测的完整代码如下:

# 凸包检测和凸缺陷
import cv2 as cv
# 读取图像
src1 = cv.imread("000.jpg")
# 转换为灰度图像
gray = cv.cvtColor(src1, cv.COLOR_BGR2GRAY)
# 二值化
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
# 获取结构元素
k = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
# 开操作
binary = cv.morphologyEx(binary, cv.MORPH_OPEN, k)
# 轮廓发现
contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# 在原图上绘制轮廓,以方便和凸包对比,发现凸缺陷
cv.drawContours(src1, contours, -1, (0, 225, 0), 3)
for c in range(len(contours)):
    # 是否为凸包
    ret = cv.isContourConvex(contours[c])
    # 凸缺陷
    # 凸包检测,returnPoints为false的是返回与凸包点对应的轮廓上的点对应的index
    hull = cv.convexHull(contours[c], returnPoints=False)
    defects = cv.convexityDefects(contours[c], hull)
    print('defects', defects)
    for j in range(defects.shape[0]):
        s, e, f, d = defects[j, 0]
        start = tuple(contours[c][s][0])
        end = tuple(contours[c][e][0])
        far = tuple(contours[c][f][0])
        # 用红色连接凸缺陷的起始点和终止点
        cv.line(src1, start, end, (0, 0, 225), 2)
        # 用蓝色最远点画一个圆圈
        cv.circle(src1, far, 5, (225, 0, 0), -1)
# 显示
cv.imshow("result", src1)
cv.waitKey(0)
cv.destroyAllWindows()

凸缺陷的部分输出显示:前三个值为凸缺陷的起始点索引、终点索引以及最深点索引(即边缘点到凸包距离最大的点)。凸包检测输出的同样为轮廓上的点的索引。

凸缺陷检测的效果图:

图中红色线条表示凸包,蓝色圆点表示凸缺陷的最深点(即边缘点到凸包距离最大的点),绿色线条表示原始轮廓。红色线条与绿色轮廓之间的区域即为凸缺陷区域。

4、总结

(1)在使用cv2.convexityDefects函数进行凸缺陷检测时,必须将凸包检测函数cv2.convexHull中的returnPoints参数设置为False,以便返回与凸包顶点对应的轮廓点索引。

(2)cv2.convexityDefects函数的返回值是一个数组序列,格式为[凸缺陷起点索引,凸缺陷终点索引,凸缺陷最深点索引,到最远点的近似距离]。前三个值为索引值,连接起点和终点即得到凸包线段。

(3)凸缺陷的最深点:即边缘点到凸包距离最大的点;到最远点的近似距离:即该边缘点到凸包的最大距离。

(4)利用凸包检测可以获取更详细的轮廓信息,可用于边界检测,结合凸缺陷分析可实现手势识别和物体识别。

以上就是OpenCV凸包检测和凸缺陷学习示例的详细内容,更多关于OpenCV凸包检测和凸缺陷的资料请关注本站其它相关文章!

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表