Python OpenCV 连通域分析(Connected Components)详解与实战
·
一、什么是连通域
连通域(Connected Components)是指图像中像素值相同且彼此连通的一组像素集合。
在工业视觉中,连通域分析通常用于将目标从背景中分离,并统计目标数量、面积、位置等关键信息。
典型处理流程
原图
↓
灰度化
↓
二值化
↓
Connected Components
↓
面积过滤
↓
目标分析
工业应用场景
- OCR 字符分割
- 胶滴检测
- 异物检测
- Connector Pin 数量统计
二、四邻域与八邻域
连通性的定义决定了像素如何被归为同一区域。
四邻域(4-Connectivity)
仅包含上下左右四个方向的连接。
X
X O X
X
八邻域(8-Connectivity)
包含上下左右及四个对角线方向的连接。
X X X
X O X
X X X
OpenCV 参数设置
# 4邻域连接
connectivity = 4
# 8邻域连接(工业视觉推荐)
connectivity = 8
建议:在大多数工业视觉场景中,推荐使用
connectivity=8以避免目标被错误分割。
三、connectedComponents() 基础用法
函数原型
num_labels, labels = cv2.connectedComponents(
image,
connectivity=8
)
参数说明
| 参数 | 说明 |
|---|---|
image | 8位单通道二值图像 |
connectivity | 连通性定义,4 或 8 |
返回值详解
num_labels:连通域总数量(包含背景)。- 例如:背景 + 2个目标 =
num_labels = 3
- 例如:背景 + 2个目标 =
labels:标签图(Label Map)。- 背景像素值为
0。 - 其他目标依次编号
1, 2, 3...
- 背景像素值为
标签图示例:
0 0 0 0
0 1 1 0
0 2 2 0
四、案例:统计目标数量
import cv2
# 1. 读取图像
img = cv2.imread("binary.png", 0)
# 2. 二值化
_, binary = cv2.threshold(
img,
0,
255,
cv2.THRESH_BINARY + cv2.THRESH_OTSU
)
# 3. 连通域分析
num_labels, labels = cv2.connectedComponents(binary)
# 4. 输出结果(减去背景)
print("目标数量:", num_labels - 1)
五、connectedComponentsWithStats() 进阶用法
相比基础函数,该函数额外返回每个连通域的统计信息和质心坐标。
函数原型
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(
binary,
connectivity=8
)
stats 统计矩阵
每一行对应一个连通域(索引0为背景),包含以下属性:
| 属性 | 常量 | 说明 |
|---|---|---|
| LEFT | cv2.CC_STAT_LEFT | 边界框左上角 X 坐标 |
| TOP | cv2.CC_STAT_TOP | 边界框左上角 Y 坐标 |
| WIDTH | cv2.CC_STAT_WIDTH | 边界框宽度 |
| HEIGHT | cv2.CC_STAT_HEIGHT | 边界框高度 |
| AREA | cv2.CC_STAT_AREA | 连通域像素面积 |
读取示例:
x = stats[i, cv2.CC_STAT_LEFT]
y = stats[i, cv2.CC_STAT_TOP]
w = stats[i, cv2.CC_STAT_WIDTH]
h = stats[i, cv2.CC_STAT_HEIGHT]
area = stats[i, cv2.CC_STAT_AREA]
centroids 质心矩阵
返回每个连通域的几何中心 (cx, cy)。
cx, cy = centroids[i]
六、完整案例:目标检测与标注
import cv2
# 1. 预处理
img = cv2.imread("binary.png", 0)
_, binary = cv2.threshold(
img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU
)
# 2. 连通域分析
num, labels, stats, centers = cv2.connectedComponentsWithStats(binary)
# 3. 创建彩色画布
color = cv2.cvtColor(binary, cv2.COLOR_GRAY2BGR)
# 4. 遍历并过滤目标
for i in range(1, num): # 从1开始,跳过背景
area = stats[i, cv2.CC_STAT_AREA]
# 面积过滤:忽略小噪点
if area < 200:
continue
# 获取边界框
x = stats[i, cv2.CC_STAT_LEFT]
y = stats[i, cv2.CC_STAT_TOP]
w = stats[i, cv2.CC_STAT_WIDTH]
h = stats[i, cv2.CC_STAT_HEIGHT]
# 绘制矩形框
cv2.rectangle(color, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 标注面积
cv2.putText(
color, str(area), (x, y - 5),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2
)
cv2.imshow("Result", color)
cv2.waitKey()
七、Blob 分析与过滤策略
连通域在机器视觉中常被称为 Blob(斑点)。常见的过滤维度包括:
- 面积 (Area):去除噪点或过大背景块。
- 宽高 (Width/Height):限制目标尺寸范围。
- 长宽比 (Aspect Ratio):筛选特定形状目标。
- 圆度 (Circularity):区分圆形与非圆形目标。
长宽比过滤示例:
ratio = w / h
if ratio < 0.5 or ratio > 2:
continue # 跳过不符合比例的目标
八、工业视觉实战案例
1. 缺件检测
通过统计有效连通域数量判断是否缺件:
if num_labels - 1 < 10:
print("报警:存在缺件")
2. OCR 字符分割
提取字符区域并送入识别引擎:
roi = image[y:y+h, x:x+w]
# cv2.imshow("Char", roi)
# result = ocr_engine.recognize(roi)
3. Connector Pin 统计
pin_count = num_labels - 1
if pin_count != expected_count:
trigger_alarm()
九、Connected Components vs findContours
| 特性 | 连通域 (Connected Components) | 轮廓 (findContours) |
|---|---|---|
| 统计数量 | ★★★★★ (极快) | ★★★★ (较快) |
| 面积过滤 | ★★★★★ (内置) | ★★★★★ (需计算) |
| 边界分析 | ★★ (仅矩形框) | ★★★★★ (任意形状) |
| 形状分析 | ★★ (基础) | ★★★★★ (拟合/矩) |
| 执行速度 | ★★★★★ | ★★★★ |
选型建议:
- 仅需计数、面积过滤、位置定位 → 优先使用 连通域。
- 需要形状拟合、轮廓点提取、复杂几何分析 → 使用 findContours。
十、常见问题排查
Q1: 为什么检测到的目标数量异常多?
原因:图像噪声过多,导致微小噪点被识别为独立连通域。
解决方案:在连通域分析前增加形态学开运算:
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
binary = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)
Q2: 为什么面积统计不正确?
- 检查二值化阈值是否准确。
- 检查目标是否发生粘连(可尝试形态学腐蚀或距离变换分水岭)。
- 确认
connectivity参数是否符合预期。
十一、总结
OpenCV 连通域分析是工业视觉中最基础且高效的工具,适用于目标计数、Blob 分析、字符分割等任务。
核心 API:
cv2.connectedComponents():轻量级计数。cv2.connectedComponentsWithStats():带统计信息的完整分析。
最佳实践:
工业项目中通常采用 形态学预处理 + 连通域分析 + 几何/面积过滤 的组合策略,可快速、稳定地完成大量目标检测任务。
更多推荐
所有评论(0)