在轮廓分析中,仅提取所有轮廓远远不够,需根据尺寸筛选目标轮廓,并通过边界框、最小面积矩形、最小包围圆等方式拟合轮廓,实现目标精准定位。本文整合完整流程,演示如何筛选 "合适轮廓" 并可视化拟合结果。
核心代码实现
python
import cv2 as cv
import numpy as np
# 1. 读取图像并校验
src = cv.imread('.\image\22.bmp')
if src is None:
print('图像读取失败,请检查路径!')
exit()
# 2. 预处理:去噪+边界填充+二值化(提升轮廓提取准确性)
dst = cv.GaussianBlur(src, (3, 3), 15) # 高斯滤波去噪
grays = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)
# 边界填充(避免图像边缘轮廓断裂)
gray = cv.copyMakeBorder(grays, 1, 1, 1, 1, cv.BORDER_CONSTANT, value=[255, 255, 255])
# 二值化(分离前景/背景)
ret, binary = cv.threshold(gray, 128, 255, cv.THRESH_BINARY)
# 3. 查找轮廓(CCOMP模式:检索内外层轮廓)
contours, hierarchy = cv.findContours(binary, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE)
# 4. 创建结果画布(避免修改原图)
result = src.copy()
# 5. 筛选并拟合轮廓
for i, contour in enumerate(contours):
# 筛选条件:轮廓尺寸在90~10000之间(过滤过小/过大噪点)
if 90 < contour.size < 10000:
# 方式1:绘制边界矩形(轴对齐)
x, y, w, h = cv.boundingRect(contour)
print(f"边界矩形尺寸:宽={w}, 高={h}")
cv.rectangle(result, (x, y), (x + w, y + h), (0, 0, 255), 3)
# 方式2:绘制最小面积矩形(旋转对齐)
rect = cv.minAreaRect(contour) # 获取最小面积矩形(中心、尺寸、旋转角度)
box = cv.boxPoints(rect) # 计算矩形四个顶点坐标
box = np.int0(box) # 坐标转为整数
cv.drawContours(result, [box], 0, (255, 255, 0), 5)
# 方式3:绘制最小包围圆
(cx, cy), radius = cv.minEnclosingCircle(contour)
center = (int(cx), int(cy))
radius = int(radius)
cv.circle(result, center, radius, (0, 255, 0), 2)
# 6. 显示结果
cv.namedWindow('src', cv.WINDOW_NORMAL)
cv.resizeWindow('src', 600, 600)
cv.imshow('src', binary) # 显示二值化图
cv.namedWindow('result', cv.WINDOW_NORMAL)
cv.resizeWindow('result', 600, 600)
cv.imshow('result', result) # 显示轮廓拟合结果
cv.waitKeyEx(0)
cv.destroyAllWindows()
关键知识点解析
1. 核心流程拆解
| 步骤 | 核心操作 | 作用说明 |
|---|---|---|
| 边界填充 | cv.copyMakeBorder() |
给图像边缘填充白色像素,避免边缘轮廓因截断无法完整提取 |
| 轮廓筛选 | contour.size |
通过轮廓像素点数量筛选,过滤过小噪点(<90)和过大背景(>10000) |
| 边界矩形 | cv.boundingRect() |
生成轴对齐的矩形框,计算简单、速度快 |
| 最小面积矩形 | cv.minAreaRect() |
生成贴合轮廓的旋转矩形,更精准匹配目标形状 |
| 最小包围圆 | cv.minEnclosingCircle() |
用圆形拟合轮廓,适用于圆形 / 类圆形目标定位 |
2. 核心参数说明
- 轮廓检索模式
cv.RETR_CCOMP:检索所有轮廓并分为两层(外层 / 内层),适合有孔洞的目标轮廓提取; contour.size:轮廓点的总像素数(每个点含 x/y 两个值,因此实际点数 = size/2);cv.boxPoints(rect):将minAreaRect返回的(中心、尺寸、角度)转换为四个顶点坐标,需转为整数才能绘制。
3. 避坑与优化技巧
- 画布赋值 :原代码
result = src是引用赋值(修改 result 会改原图),改为result = src.copy()深拷贝; - 轮廓尺寸阈值:90/10000 是经验值,需根据图像分辨率和目标大小调整(分辨率大则阈值相应增大);
- 拟合方式选择 :
- 轴对齐矩形:适合规则、无旋转的目标;
- 最小面积矩形:适合倾斜、旋转的目标;
- 最小包围圆:适合圆形目标(如表盘、零件)。
- 效率优化:若仅需一种拟合方式,注释其他方式可提升运行速度。
总结
- 轮廓筛选的核心是通过
contour.size过滤无效轮廓,阈值需根据实际场景调整; - 边界填充是提取图像边缘轮廓的关键预处理步骤,避免轮廓断裂;
- 三种拟合方式各有适用场景:轴对齐矩形(快)、最小面积矩形(准)、最小包围圆(适配圆形目标)。