计算机视觉基础|第 6 章 轮廓检测、轮廓特征与轮廓近似

目录

前言

[1 、轮廓检测](#1 、轮廓检测)

[1.1 轮廓与边缘的区别](#1.1 轮廓与边缘的区别)

[1.2 核心 API](#1.2 核心 API)

[cv2.findContours () 查找轮廓](#cv2.findContours () 查找轮廓)

[cv2.drawContours () 绘制轮廓](#cv2.drawContours () 绘制轮廓)

[1.3 轮廓检测基础代码](#1.3 轮廓检测基础代码)

2、轮廓特征

[1.轮廓面积 contourArea](#1.轮廓面积 contourArea)

[2.轮廓周长 arcLength](#2.轮廓周长 arcLength)

[3.外接矩形 boundingRect(正外接矩形,不旋转)](#3.外接矩形 boundingRect(正外接矩形,不旋转))

[4.最小外接旋转矩形 minAreaRect](#4.最小外接旋转矩形 minAreaRect)

[5.轮廓重心(矩 Moments)](#5.轮廓重心(矩 Moments))

3、轮廓近似

[3.1 原理](#3.1 原理)

[3.2 API](#3.2 API)

[3.3 完整综合代码](#3.3 完整综合代码)

​编辑

4、本章小结


前言

承接第 8 章边缘检测。边缘检测只能得到零散的边界像素,轮廓检测可以把同一物体的边界像素组合成一条完整闭合轮廓,常用于物体计数、形状识别、目标分割,是传统计算机视觉高频模块。

1 、轮廓检测

1.1 轮廓与边缘的区别

  • 边缘:图像灰度发生突变的像素点,线条零散,不一定闭合。

  • 轮廓 :经过算法分组之后,属于同一个物体的闭合边界点集合,可以做后续计算。

重要前提:cv2.findContours() 输入优先使用二值图像 ,黑色为背景,白色为待检测目标。 标准处理流水线:彩色图 → 灰度图 → 二值化 threshold → 查找轮廓。

1.2 核心 API

cv2.findContours () 查找轮廓
python 复制代码
contours, hierarchy = cv2.findContours(binary_img, mode, method)
  • contours:轮廓列表,存储图像中所有检测到的轮廓。整体为元组嵌套列表结构,每个子列表对应一条独立轮廓,由一组物体边界的 (x,y) 坐标点组成,可单独提取、处理单条轮廓。

  • hierarchy:轮廓层级,用于处理嵌套轮廓(物体内部存在孔洞)。

检索模式 mode

  • cv2.RETR_EXTERNAL:只提取最外层轮廓,忽略内部孔洞,日常最常用。

  • cv2.RETR_TREE:输出完整的嵌套层级关系,处理孔洞、内外轮廓。

轮廓点存储方式 method

  • cv2.CHAIN_APPROX_SIMPLE:压缩轮廓点,去掉重复冗余点,节省内存,推荐使用。

  • cv2.CHAIN_APPROX_NONE:保存边界上全部像素点,点数量大。

cv2.drawContours () 绘制轮廓
python 复制代码
cv2.drawContours(dst_img, contours, index, color, thickness)
  • dst_img:绘制轮廓的目标图像,必须传入原图副本,避免修改原始图像。

  • contours:需要绘制的轮廓列表,为 findContours 检测得到的轮廓数组。

  • index:轮廓索引,-1 代表绘制所有轮廓;传入具体数字(如0、1)仅绘制对应序号的单条轮廓。

  • color:轮廓绘制颜色,遵循 OpenCV 的 BGR 通道格式,例如(0,0,255) 为红色、(0,255,0) 为绿色。

  • thickness:轮廓线条宽度,单位为像素;设置为 -1 可填充整个轮廓内部区域

1.3 轮廓检测基础代码

python 复制代码
import cv2
读取原图
phone = cv2.imread(r'D:\pythoncode2\bigdata_ai40\Image\phone.png')
转换灰度图
phone_gray = cv2.cvtColor(phone, cv2.COLOR_BGR2GRAY)
cv2.imshow('phone_gray', phone_gray)
cv2.waitKey(0)
二值化处理:分割前景与背景,生成黑白二值图
ret, phone_binary = cv2.threshold(phone_gray, 127, 255, cv2.THRESH_BINARY)
cv2.imshow('phone_binary', phone_binary)
cv2.waitKey(0)
查找轮廓
[-2] 兼容所有OpenCV版本,稳定获取轮廓列表
RETR_TREE:提取完整层级轮廓(包含内部孔洞)
CHAIN_APPROX_NONE:保留轮廓全部像素点
contours = cv2.findContours(phone_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[-2]
print(f"检测到轮廓数量:{len(contours)}")
绘制所有轮廓
img_copy = phone.copy()
cv2.drawContours(image=img_copy, contours=contours, contourIdx=-1, color=(0, 0, 255), thickness=3)
cv2.imshow('phone_contour', img_copy)
cv2.waitKey(0)
释放所有窗口
cv2.destroyAllWindows()

2、轮廓特征

拿到单条轮廓 cnt = contoursi,可以计算物体各类几何特征,用于筛选目标物体。

1.轮廓面积 contourArea

python 复制代码
area = cv2.contourArea(cnt)

作用:过滤噪声小轮廓,设置面积阈值,把过小干扰轮廓剔除。

2.轮廓周长 arcLength

python 复制代码
peri = cv2.arcLength(cnt, closed=True)

closed=True 代表轮廓是闭合图形;周长是轮廓近似的重要输入参数。

3.外接矩形 boundingRect(正外接矩形,不旋转)

python 复制代码
x, y, w, h = cv2.boundingRect(cnt)
  • x,y:矩形左上角坐标;w,h:宽、高。
    可以画矩形:cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),2)

4.最小外接旋转矩形 minAreaRect

python 复制代码
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.intp(box)
cv2.drawContours(img, [box], 0, (255, 0, 0), 2)

可以得到旋转角度,适合倾斜物体。

5.轮廓重心(矩 Moments)

python 复制代码
M = cv2.moments(cnt)
cx = int(M["m10"] / M["m00"])
cy = int(M["m01"] / M["m00"])

获取物体中心点坐标。

使用场景:通过面积、宽高比筛选,只保留我们感兴趣的物体轮廓。

3、轮廓近似

3.1 原理

原始轮廓包含大量点,图像噪声会带来很多毛刺、抖动。

轮廓近似 approxPolyDP 使用道格拉斯‑普克算法,用少量顶点多边形去拟合原始复杂轮廓。

3.2 API

python 复制代码
approx = cv2.approxPolyDP(curve, epsilon, closed)
  • curve:输入单条轮廓,不能直接传入全部 contours 列表。
  • epsilon:近似精度,最核心超参数,通常取轮廓周长的比例:
    epsilon = 0.04 * cv2.arcLength(cnt, True)
  • epsilon 越大:顶点越少,轮廓越粗糙;
  • epsilon 越小:顶点越多,越贴近原始轮廓。
  • closed=True:表示处理闭合轮廓。

|-----------------------|
| 根据返回approx顶点数量,做形状识别: |

  • 3 个顶点 → 三角形
  • 4 个顶点 → 矩形、正方形
  • 大量顶点 → 圆形或者不规则图形

3.3 完整综合代码

python 复制代码
import cv2
import numpy as np
读取图像
img = cv2.imread(r'D:\pythoncode2\bigdata_ai40\Image\shape.png')
origin_img = img.copy()
图像预处理:灰度转换 + 二值化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
查找外层轮廓,兼容所有OpenCV版本
contours = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]
绘制原始完整轮廓
cv2.drawContours(origin_img, contours, -1, (0, 255, 0), 2)
遍历所有轮廓,计算特征、绘制矩形并执行轮廓近似
for cnt in contours:
# 1. 计算轮廓面积,过滤微小噪声轮廓
area = cv2.contourArea(cnt)
if area < 50:
continue
# 2. 计算闭合轮廓周长
peri = cv2.arcLength(cnt, closed=True)

# 3. 轮廓近似:通过周长比例设置精度
epsilon = 0.04 * peri
approx = cv2.approxPolyDP(cnt, epsilon, closed=True)

# 绘制近似后的多边形轮廓
cv2.drawContours(img, [approx], -1, (255, 0, 0), 2)

# 4. 绘制正外接矩形(不旋转)
x, y, w, h = cv2.boundingRect(approx)
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 255), 2)

# 5. 绘制最小外接旋转矩形(适配倾斜物体)
min_rect = cv2.minAreaRect(cnt)
min_box = cv2.boxPoints(min_rect)
min_box = np.intp(min_box)
cv2.drawContours(img, [min_box], 0, (255, 255, 0), 2)

# 识别轮廓顶点数量并标注
point_num = len(approx)
cv2.putText(img, f"pts:{point_num}", (x, y-8),
            cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
展示结果
cv2.imshow("raw_contour", origin_img)
cv2.imshow("approx_feature_result", img)
cv2.waitKey(0)
释放所有窗口
cv2.destroyAllWindows()

4、本章小结

  1. 轮廓是闭合物体点集,由二值图像提取,区别于零散边缘。

  2. 轮廓特征包含面积、周长、外接矩形、重心,用于筛选目标物体。

  3. 轮廓近似approxPolyDP依靠 epsilon 控制精度,依靠顶点数目实现简单形状识别。

  4. 典型场景:零件检测、答题卡识别、图形分类、物体计数。

相关推荐
leoZ23115 小时前
Vue3 还原一个企业级后台-01-项目背景与选题
图像处理·人工智能·chatgpt·智慧城市·边缘计算·openvino·dreamfusion
武汉万象奥科18 小时前
8路AHD摄像头同时输出演示,万象奥科RK3576 AHD硬件方案
人工智能·计算机视觉
别动我齐刘海21 小时前
机器学习基础2——C++、OpenCV、点云、Open3D
c++·人工智能·opencv·机器学习·计算机视觉·机器人·ros2
生命涌现1 天前
【生命涌现植物健康分析】在火山云Agent平台的使用教程
人工智能·计算机视觉·agent·多模态大模型·openclaw小龙虾技能
雪碧透心凉_1 天前
Python OpenCV图像处理入门
图像处理·python·opencv
躺不平的理查德1 天前
OpenCV Mat 备忘录
人工智能·opencv·计算机视觉
欧特克_Glodon1 天前
OpenCV计算机视觉开发入门与实践<二>:图像噪声与图像处理
c++·图像处理·opencv·计算机视觉
动物园猫1 天前
桑叶病害目标检测数据集:16,000张图像 | 目标检测
人工智能·目标检测·计算机视觉
ʜᴇɴʀʏ1 天前
ICCV 2025 | STEP-DETR:基于超级教师与伪标签引导文本查询的半监督目标检测
人工智能·目标检测·计算机视觉·transformer