【Python】【OpenCV】`cv2.findContours()`、`cv2.drawContours()`和`cv2.contourArea()`函数详解和运行示例

在计算机视觉领域,轮廓检测是图像处理中非常重要的一部分,而 OpenCV 提供了一系列函数用于实现轮廓的检测、绘制及面积计算等操作。本文将详细讲解 OpenCV 中的 cv2.findContours()cv2.drawContours()cv2.contourArea() 函数的用法,并结合代码示例与图解帮助你快速掌握这些技能。


一、什么是轮廓?

轮廓(Contour) 是指边界或边缘,它描述了连接具有相同强度或颜色像素点的曲线。
在图像处理中,轮廓经常用于:

  1. 形状分析:识别目标形状。
  2. 目标检测:检测物体的边缘。
  3. 特征提取:如面积、周长等。

二、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():计算轮廓面积,用于形状分析。

通过上述函数的结合,你可以轻松实现轮廓检测、绘制及特征提取。在实际项目中,轮廓处理常用于物体分割、形状识别和目标跟踪。
动手实践并将这些函数应用到你的图像处理中吧!

最后修改于:2024年11月26日 21:04

评论已关闭

推荐阅读

DDPG 模型解析,附Pytorch完整代码
2024年11月24日
DQN 模型解析,附Pytorch完整代码
2024年11月24日
AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日