【Python】【OpenCV】`cv2.findContours()`、`cv2.drawContours()`和`cv2.contourArea()`函数详解和运行示例
在计算机视觉领域,轮廓检测是图像处理中非常重要的一部分,而 OpenCV 提供了一系列函数用于实现轮廓的检测、绘制及面积计算等操作。本文将详细讲解 OpenCV 中的 cv2.findContours()
、cv2.drawContours()
和 cv2.contourArea()
函数的用法,并结合代码示例与图解帮助你快速掌握这些技能。
一、什么是轮廓?
轮廓(Contour) 是指边界或边缘,它描述了连接具有相同强度或颜色像素点的曲线。
在图像处理中,轮廓经常用于:
- 形状分析:识别目标形状。
- 目标检测:检测物体的边缘。
- 特征提取:如面积、周长等。
二、cv2.findContours()
函数详解
1. 函数原型
contours, hierarchy = cv2.findContours(image, mode, method)
2. 参数详解
image
:输入图像,需为二值化图像(通常使用cv2.threshold()
或cv2.Canny()
预处理)。mode
:轮廓检索模式,常见选项:cv2.RETR_EXTERNAL
:仅检索外部轮廓。cv2.RETR_TREE
:检索所有轮廓并构建完整层次结构。cv2.RETR_LIST
:检索所有轮廓,无层次关系。
method
:轮廓近似方法,常见选项:cv2.CHAIN_APPROX_NONE
:保存所有轮廓点。cv2.CHAIN_APPROX_SIMPLE
:仅保存拐点坐标,减少冗余点。
3. 返回值
contours
:轮廓点列表,每个轮廓是一个numpy
数组。hierarchy
:轮廓的层次结构。
4. 示例代码
以下代码展示如何使用 cv2.findContours()
提取图像轮廓:
import cv2
import numpy as np
# 读取图像
image = cv2.imread("shapes.png", cv2.IMREAD_GRAYSCALE)
# 二值化图像
_, binary = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)
# 检测轮廓
contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 打印轮廓信息
print(f"检测到的轮廓数量: {len(contours)}")
示例输出
检测到的轮廓数量: 3
三、cv2.drawContours()
函数详解
1. 函数原型
cv2.drawContours(image, contours, contourIdx, color, thickness)
2. 参数详解
image
:目标图像,绘制结果将在此图像上显示。contours
:轮廓点列表,由cv2.findContours()
返回。contourIdx
:-1
:绘制所有轮廓。- 正整数:绘制指定索引的轮廓。
color
:轮廓颜色,通常为 BGR 格式元组,如(0, 255, 0)
表示绿色。thickness
:轮廓线条粗细,-1
表示填充轮廓内部。
3. 示例代码
以下代码绘制所有轮廓:
# 读取图像
image_color = cv2.imread("shapes.png")
# 绘制轮廓
cv2.drawContours(image_color, contours, -1, (0, 255, 0), 2)
# 显示图像
cv2.imshow("Contours", image_color)
cv2.waitKey(0)
cv2.destroyAllWindows()
示例效果图
原图:
- 二值化后,轮廓被绿色线条标出。
四、cv2.contourArea()
函数详解
1. 函数原型
area = cv2.contourArea(contour)
2. 参数详解
contour
:单个轮廓点的数组(通常由cv2.findContours()
提供)。- 返回值:轮廓的面积(以像素为单位)。
3. 示例代码
计算每个轮廓的面积:
for i, contour in enumerate(contours):
area = cv2.contourArea(contour)
print(f"轮廓 {i} 的面积: {area}")
示例输出
轮廓 0 的面积: 1234.5
轮廓 1 的面积: 567.8
轮廓 2 的面积: 890.3
五、综合示例:结合三大函数完成完整流程
以下代码展示如何检测图像中的所有轮廓,绘制并计算其面积:
import cv2
import numpy as np
# 读取图像
image = cv2.imread("shapes.png", cv2.IMREAD_GRAYSCALE)
image_color = cv2.imread("shapes.png")
# 二值化
_, binary = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)
# 检测轮廓
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 遍历轮廓
for i, contour in enumerate(contours):
# 绘制当前轮廓
cv2.drawContours(image_color, [contour], -1, (0, 255, 0), 2)
# 计算轮廓面积
area = cv2.contourArea(contour)
print(f"轮廓 {i} 的面积: {area}")
# 显示结果
cv2.imshow("Contours", image_color)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行效果图
在原始图像上绘制绿色的轮廓线,并输出每个轮廓的面积。
六、常见问题及解决方法
1. 为什么 cv2.findContours()
输入图像必须二值化?
- 二值化后,图像中像素值为 0(黑色)或 255(白色),轮廓检测更准确。
2. 如何区分外轮廓和内轮廓?
- 设置
mode=cv2.RETR_EXTERNAL
检测外轮廓。 - 设置
mode=cv2.RETR_TREE
获取内外轮廓的层次关系。
3. 如何填充轮廓内部?
- 在
cv2.drawContours()
中,将thickness
设置为-1
。
七、总结
cv2.findContours()
:用于检测图像中的轮廓。cv2.drawContours()
:绘制轮廓,支持单个或所有轮廓。cv2.contourArea()
:计算轮廓面积,用于形状分析。
通过上述函数的结合,你可以轻松实现轮廓检测、绘制及特征提取。在实际项目中,轮廓处理常用于物体分割、形状识别和目标跟踪。
动手实践并将这些函数应用到你的图像处理中吧!
评论已关闭