3.2 查找与绘制轮廓
总目录:1.1 OpenCV介绍与学习路线 | 第三章:边缘、轮廓与几何 | 编号:3.2
← 上一节:3.1 Canny边缘检测 | 下一节:3.3 轮廓层级 →
3.2 查找与绘制轮廓
边缘图告诉我们“哪里变化大”,轮廓则把相连的边界点组织成一组一组的曲线。这样我们才能对每个目标分别算面积、周长和中心。
一、边缘与轮廓有什么区别
Canny 输出:一张黑白边缘图
findContours 输出:多个点集组成的 Python 列表
一张边缘图里可能有 20 个闭合形状,findContours 会尽量把它们拆成 20 组点。轮廓是数据结构,不是一张图。
二、findContours:从二值图提取边界点
contours, hierarchy = cv2.findContours(
binary,
cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE,
)
输入通常是 8 位单通道二值图。OpenCV 把非零区域视为前景,因此常见情况是“白目标、黑背景”。
if binary.ndim != 2:
raise ValueError("findContours 常规输入应为单通道二值图")
三、检索模式与近似方法
先记两个最常用组合:
# 只要最外层目标
cv2.RETR_EXTERNAL
# 要保留父子嵌套
cv2.RETR_TREE
完整层级放在 3.3 轮廓层级。
点保存方法:
| 方法 | 含义 |
|---|---|
CHAIN_APPROX_NONE |
保存边界上的大量点 |
CHAIN_APPROX_SIMPLE |
压缩直线段,只保留必要端点 |
矩形的一条直边没必要记几百个像素点,所以日常优先 CHAIN_APPROX_SIMPLE。
四、轮廓列表和点集形状
print(type(contours)) # tuple 或 list 风格的轮廓集合,依绑定版本而定
print(len(contours))
print(contours[0].shape) # 常见 (N, 1, 2)
每个轮廓是一个 NumPy 点集。(N, 1, 2) 的解释见 四、轮廓点为什么是 (N, 1, 2)。
按面积过滤小噪声:
large_contours = [
cnt for cnt in contours
if cv2.contourArea(cnt) >= 500
]
面积阈值依赖分辨率和目标距离,500 只是示例。
五、drawContours:把轮廓画出来
result = image.copy()
cv2.drawContours(result, contours, -1, (0, 255, 0), 2)
-1:画全部轮廓;0:只画第 0 个轮廓;thickness=-1:填充轮廓内部。
逐个画并标索引:
for index, contour in enumerate(contours):
color = (0, 255, 0)
cv2.drawContours(result, contours, index, color, 2)
x, y, w, h = cv2.boundingRect(contour)
cv2.putText(result, str(index), (x, max(20, y - 5)),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)
这对理解 hierarchy 很有帮助:图上能看到轮廓编号,数组里的父子索引就不再是天书。
最小完整示例
import cv2
image = cv2.imread("shapes.png")
if image is None:
raise FileNotFoundError("shapes.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)
contours, hierarchy = cv2.findContours(
binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)
result = image.copy()
cv2.drawContours(result, contours, -1, (0, 255, 0), 2)
cv2.imshow("Binary", binary)
cv2.imshow("Contours", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
六、参考
← 上一节:3.1 Canny边缘检测 | 下一节:3.3 轮廓层级 →
留言区
不收集任何个人信息;昵称只绑定浏览器里的随机 Cookie。