一、什么是图像轮廓?
在计算机视觉中,轮廓(Contour)是指物体边界上的连续点集合,它描述了物体的外形结构。
简单来说:轮廓就是图像中物体边缘的线条表示。
例如:
- 手机外形
- 人脸轮廓
- 车辆边界
- 字符形状
都可以通过轮廓进行描述。
轮廓检测主要应用于:
- 目标检测
- 形状分析
- 图像分割
- 目标跟踪
- 物体测量
轮廓检测的基本流程:
原始图像
↓
灰度化
↓
二值化处理
↓
轮廓检测
↓
轮廓分析
↓
绘制结果
二、轮廓检测前的准备工作
1. 为什么需要二值化?
OpenCV中的轮廓检测要求输入图像必须是二值图像。
也就是说:
- 黑色像素:0
- 白色像素:255
只有这样,OpenCV才能区分背景区域和目标区域。
代码首先读取图片:
phone = cv2.imread('phone.png')
然后转换为灰度图:
phone_gray = cv2.cvtColor(
phone,
cv2.COLOR_BGR2GRAY
)
最后进行二值化处理:
ret,phone_binary=cv2.threshold(
phone_gray,
127,
255,
cv2.THRESH_BINARY
)
三、OpenCV轮廓检测函数
1. findContours函数
OpenCV使用:
cv2.findContours()
进行轮廓检测。
函数格式:
contours,hierarchy=cv2.findContours(
image,
mode,
method
)
示例代码:
contours=cv2.findContours(
phone_binary,
cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE
)[-2]
该函数返回两个重要结果:
(1)contours——轮廓列表
contours保存图像中所有轮廓信息。
每一个轮廓都是由多个坐标点组成:
(x,y)
例如:
contours[0]
表示第一个检测到的轮廓。
(2)hierarchy——轮廓层级结构
hierarchy描述不同轮廓之间的关系。
包含4个值:
[Next,Previous,First Child,Parent]
含义:
| Next | 同一级别的下一个轮廓 |
| Previous | 同一级别的上一个轮廓 |
| First Child | 当前轮廓的子轮廓 |
| Parent | 当前轮廓的父轮廓 |
例如一个圆环:
外部圆轮廓
|
内部空洞轮廓
四、轮廓检索模式
findContours函数第二个参数mode决定轮廓之间的组织方式。
代码中使用:
cv2.RETR_TREE
1.RETR_EXTERNAL
只检测最外层轮廓。
例如:
********
* *
* **** *
* * * *
* **** *
********
只返回最外面的边界。
2.RETR_LIST
检测所有轮廓。
但是不建立层级关系,所有轮廓属于同一级。
3.RETR_CCOMP
建立两级轮廓结构:
第一层:
物体外轮廓
第二层:
内部孔洞轮廓
4.RETR_TREE
建立完整的轮廓树结构。
例如:
对象
|
├──内部区域
|
└──子对象
适用于复杂目标分析。
五、轮廓近似方法
findContours第三个参数method用于控制轮廓点保存方式。
1.CHAIN_APPROX_NONE
保存所有轮廓点。
例如一个矩形:
1000个边界点
全部保存。
优点:精度高。
缺点:数据量大。
2.CHAIN_APPROX_SIMPLE
对轮廓进行压缩,只保存关键点。
例如矩形:
只需要保存:
左上角
右上角
右下角
左下角
即可表示整个轮廓。
代码:
cv2.CHAIN_APPROX_SIMPLE
六、轮廓绘制
检测到轮廓后,可以使用:
cv2.drawContours()
进行绘制。
函数:
cv2.drawContours(
image,
contours,
contourIdx,
color,
thickness
)
示例:
image_copy=phone.copy()
cv2.drawContours(
image_copy,
contours,
-1,
(0,25,250),
2
)
参数说明:
| image | 绘制轮廓的图像 |
| contours | 轮廓列表 |
| contourIdx | 指定轮廓编号 |
| color | 轮廓颜色 |
| thickness | 线条粗细 |
其中:
contourIdx=-1
表示绘制所有轮廓。
七、轮廓特征分析
轮廓检测后,可以进一步分析:
- 面积
- 周长
- 大小
- 位置
- 外接形状
1.轮廓面积
函数:
cv2.contourArea(contour)
作用:计算轮廓区域面积。
示例:
area_0=cv2.contourArea(contours[0])
print(area_0)
单位:像素平方。
2.轮廓周长
函数:
cv2.arcLength(curve,closed)
参数:
| curve | 轮廓点 |
| closed | 是否闭合 |
示例:
length=cv2.arcLength(
contours[0],
closed=True
)
如果是封闭图形:
- 圆
- 矩形
- 手机外形
通常设置:
closed=True
八、根据面积筛选轮廓
实际检测中会产生很多无用轮廓,例如:
- 噪声
- 小区域
- 背景边缘
可以通过面积过滤。
代码:
a_list=[]
for i in contours:
if cv2.contourArea(i)>10000:
a_list.append(i)
作用:
只保留面积大于10000的轮廓。
应用:
- 去除噪声
- 保留主要目标
九、寻找最大轮廓
很多任务只需要最大的目标。
代码:
sortcnt=sorted(contours,key=cv2.contourArea,reverse=True)[0]
执行过程:
1.根据面积排序
2.降序排列
3.取第一个元素得到最大轮廓。
十、轮廓外接圆
函数:
cv2.minEnclosingCircle()
作用:计算能够完全包围轮廓的最小圆。
代码:
(x,y),r=cv2.minEnclosingCircle(cnt)
返回:
- 圆心坐标(x,y)
- 半径r
绘制:
cv2.circle(
phone,
(int(x),int(y)),
int(r),
(0,255,255),
2
)

应用:
- 人脸检测
- 球体检测
- 圆形目标定位
十一、轮廓外接矩形
函数:
cv2.boundingRect()
作用:
计算轮廓最小外接矩形。
返回:
x,y,w,h
含义:
| x | 左上角横坐标 |
| y | 左上角纵坐标 |
| w | 宽度 |
| h | 高度 |
代码:
x,y,w,h=cv2.boundingRect(cnt)
绘制:
cv2.rectangle(phone,(x,y),(x+w,y+h),(0,255,2),3)

十二、总结
常用函数:
| cv2.findContours | 寻找轮廓 |
| cv2.drawContours | 绘制轮廓 |
| cv2.contourArea | 计算面积 |
| cv2.arcLength | 计算周长 |
| cv2.boundingRect | 外接矩形 |
| cv2.minEnclosingCircle | 外接圆 |
通过轮廓检测,计算机能够从像素信息中提取物体形状,为目标检测、图像识别和自动测量提供基础。


