📌 轮廓检测(Contour Detection)
1. 什么是轮廓检测?
在图像处理中,轮廓(Contour) 是指沿着相同颜色或灰度值边界的连续曲线。
通过轮廓检测,我们可以获取物体的形状、大小、位置等信息,这在 目标检测、物体识别、图像分割、测量分析 等应用中非常常见。
⚠️ 注意:轮廓检测需要在 二值化图像 上进行,也就是说图像中的像素值必须是 0(黑色)或 255(白色),这样轮廓才会清晰。
2. 轮廓检测函数 —— cv2.findContours
image, contours, hierarchy = cv2.findContours(img, mode, method)
参数说明:
参数名 | 说明 |
---|---|
image | 输入的二值化图像(黑白图,像素值仅 0 和 255)。⚠️ 原图会被修改,通常先用 copy() 。 |
mode | 轮廓检索模式:• cv2.RETR_EXTERNAL :只检测最外层轮廓• cv2.RETR_LIST :检测所有轮廓,不建立层级关系• cv2.RETR_CCOMP :返回两层结构,外轮廓为第 1 层,内孔洞为第 2 层• cv2.RETR_TREE :返回所有轮廓,建立完整树形结构 |
method | 轮廓近似方法:• cv2.CHAIN_APPROX_NONE :保留轮廓上所有点(点数多,占内存)• cv2.CHAIN_APPROX_SIMPLE :压缩冗余点,仅保留端点(推荐,节省空间) |
contours | 可选参数,一般不用,传入已有的轮廓数据。 |
hierarchy | 可选参数,一般不用,传入已有的层次结构。 |
offset | 偏移量,所有轮廓点坐标会加上此偏移值(常用于 ROI 情况)。 |
-
img:输入图像(必须是二值化图像)。
-
mode:轮廓检索模式(决定如何组织轮廓层次结构)
-
cv2.RETR_EXTERNAL
:只检测最外层的轮廓,忽略内部轮廓。 -
cv2.RETR_LIST
:检测所有轮廓,但不建立层次结构。 -
cv2.RETR_CCOMP
:返回两层结构,外轮廓为第 1 层,内孔洞为第 2 层。 -
cv2.RETR_TREE
:返回所有轮廓,并建立完整的层次结构(树形结构)。
-
-
method:轮廓近似方法
-
cv2.CHAIN_APPROX_NONE
:保存轮廓上的所有点。 -
cv2.CHAIN_APPROX_SIMPLE
:压缩冗余点,只保留拐点。
-
返回值:
-
image:输入图像的副本(OpenCV 旧版本返回3个,新版本只返回2个)。
-
contours:一个 Python 列表,包含所有轮廓,每个轮廓是一个
numpy.ndarray
,存储轮廓点坐标(x,y)
。 -
hierarchy:轮廓的层次结构数组,每个元素包含
[Next, Previous, First_Child, Parent]
。
3. 层次结构(Hierarchy)
hierarchy
是一个 numpy
数组,形状为 (1, 轮廓数量, 4)
,含义如下:
-
Next:同一层级的下一个轮廓索引。
-
Previous:同一层级的上一个轮廓索引。
-
First Child:第一个子轮廓索引。
-
Parent:父轮廓索引。
例如,检测一个带孔洞的圆,外圆是父轮廓,内圆是子轮廓。
4. 绘制轮廓 —— cv2.drawContours
cv2.drawContours(image, contours, contourIdx, color, thickness)
参数说明:
参数名 | 类型 | 说明 |
---|---|---|
image | ndarray | 要绘制轮廓的输入图像(一般是原图或副本) |
contours | list | 由 cv2.findContours() 返回的轮廓列表 |
contourIdx | int | 要绘制的轮廓索引:• -1 :绘制所有轮廓• 0,1,2,... :绘制指定索引的轮廓 |
color | (B,G,R) 元组 | 轮廓颜色,例如 (0,255,0) 表示绿色 |
thickness | int | 轮廓线条的粗细,-1 表示填充轮廓区域 |
lineType | int(可选) | 线条类型,默认 cv2.LINE_8 |
hierarchy | ndarray (可选) | 轮廓层次结构(由 findContours 返回),可用于选择性绘制 |
maxLevel | int(可选) | 绘制的最大轮廓层级,0 只绘制当前层级,1 包括子轮廓,以此类推 |
offset | (x,y) 元组(可选) | 绘制时对轮廓坐标的偏移量 |
-
image:要绘制轮廓的图像。
-
contours:由
cv2.findContours()
返回的轮廓列表。 -
contourIdx:要绘制的轮廓索引,
-1
表示绘制所有轮廓。 -
color:绘制颜色(BGR 格式,例如
(0,255,0)
表示绿色)。 -
thickness:线条粗细,
-1
表示填充整个轮廓。
5. 代码示例:手机轮廓检测
图片准备:可直接使用下图,也可以自备图片
以下所有处理后的图片:
import cv2
# 1. 读取图像
phone = cv2.imread('phone.png')
phone_gray = cv2.cvtColor(phone, cv2.COLOR_BGR2GRAY)
# 2. 二值化处理
ret, phone_binary = cv2.threshold(phone_gray, 120, 255, cv2.THRESH_BINARY)
# 3. 查找轮廓
_, contours, hierarchy = cv2.findContours(phone_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
print("层次结构:", hierarchy)
print("轮廓数量:", len(contours))
# 4. 绘制轮廓
image_copy = phone.copy()
cv2.drawContours(image_copy, contours, -1, (0, 255, 0), 2)
cv2.imshow('phone', phone)
cv2.imshow('phone_gray', phone_gray)
cv2.imshow('Binary Image', phone_binary)
cv2.imshow('Contours Detected', image_copy)
cv2.waitKey(0)
cv2.destroyAllWindows()
6. 实验效果
-
二值化图像:显示手机黑白分割后的结果。
-
绘制轮廓图像:显示绿色线条勾勒出的手机外轮廓和按钮等细节。
7. 轮廓检测的应用
-
物体识别:通过轮廓形状判断物体类别。
-
目标跟踪:提取目标的轮廓进行追踪。
-
测量分析:计算物体的面积、周长、重心。
-
图像分割:通过轮廓划分前景与背景。
8. 注意事项
-
必须二值化:直接用彩色图像检测会失败。
-
噪声干扰:噪声会被识别为小轮廓,可在检测前进行 平滑处理。
-
选择合适的
mode
:根据任务需求选择RETR_EXTERNAL
或RETR_TREE
。 -
层次结构:在复杂图像中,理解
hierarchy
对处理父子轮廓很重要。
✅ 总结:
轮廓检测是图像处理中非常基础且重要的操作。通过 cv2.findContours()
获取轮廓,再配合 cv2.drawContours()
进行可视化,我们不仅能提取图像的外形,还能进行更复杂的几何分析,为后续的目标检测和图像理解打下基础。