当前位置: 首页 > ds >正文

OpenCV 在二值图像中查找轮廓 cv2.findContours

OpenCV 在二值图像中查找轮廓 cv2.findContours

flyfish

1. Contours(轮廓)的含义

在图像处理中,Contours(轮廓)指的是图像中具有相同颜色或者灰度值的连续点所构成的曲线,它可以用来表示物体的边界。简单来说,轮廓就是将物体的边缘连接起来形成的封闭曲线。轮廓在很多计算机视觉任务中都非常重要,比如物体检测、形状分析、目标识别等。通过分析轮廓的特征,如面积、周长、形状等,可以对物体进行分类和识别。

2. cv2.findContours 函数的作用

cv2.findContours 是 OpenCV 库中的一个函数,其主要作用是在二值图像中查找物体的轮廓。通常在使用这个函数之前,需要对图像进行预处理,如灰度化、二值化等操作,以便更好地提取物体的轮廓。

3. 函数语法和参数

contours, hierarchy = cv2.findContours(image, mode, method)
  • 参数说明
    • image:输入的二值图像,通常是经过阈值处理或者边缘检测后的图像。
    • mode:轮廓检索模式,用于指定查找轮廓的方式,常见的取值有:
      • cv2.RETR_EXTERNAL:只检索最外层的轮廓。
      • cv2.RETR_LIST:检索所有的轮廓,并将它们存储在一个列表中,不建立轮廓之间的层次关系。
      • cv2.RETR_TREE:检索所有的轮廓,并建立完整的轮廓层次结构。
    • method:轮廓近似方法,用于指定如何近似轮廓的曲线,常见的取值有:
      • cv2.CHAIN_APPROX_NONE:存储所有的轮廓点,即不进行近似处理。
      • cv2.CHAIN_APPROX_SIMPLE:只保留轮廓的端点,对于水平、垂直和对角线方向的直线段,只保留其端点,从而减少存储的点数。
  • 返回值
    • contours:一个列表,包含了检测到的所有轮廓,每个轮廓是一个由点组成的 NumPy 数组。
    • hierarchy:一个 NumPy 数组,用于表示轮廓之间的层次关系,对于不同的轮廓检索模式,其含义不同。

4. 示例代码

以下是一个简单的示例代码,展示如何使用 cv2.findContours 函数查找图像中的轮廓:

import cv2
import numpy as np# 读取图像
image = cv2.imread('example.jpg', 0)# 进行阈值处理,得到二值图像
_, binary = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)# 查找轮廓
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 在原始图像上绘制轮廓
contour_image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
cv2.drawContours(contour_image, contours, -1, (0, 255, 0), 2)# 显示原始图像和绘制轮廓后的图像
cv2.imshow('Original Image', image)
cv2.imshow('Contour Image', contour_image)# 等待按键事件
cv2.waitKey(0)# 关闭所有窗口
cv2.destroyAllWindows()

可以直观地看到 cv2.findContours 函数查找图像中的轮廓,并将其绘制出来。

import cv2
import numpy as np# 读取图像
image = cv2.imread('example.jpg')
# 转换为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 进行高斯模糊,减少噪声
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# 进行阈值处理,得到二值图像
_, binary = cv2.threshold(blurred, 127, 255, cv2.THRESH_BINARY)# 查找轮廓
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 初始化最大面积和对应的轮廓
max_area = 0
max_contour = None# 遍历每个轮廓,找出面积最大的轮廓
for contour in contours:# 计算轮廓的面积area = cv2.contourArea(contour)if area > max_area:max_area = areamax_contour = contourif max_contour is not None:# 计算最大面积轮廓的周长perimeter = cv2.arcLength(max_contour, True)# 计算最大面积轮廓的凸包hull = cv2.convexHull(max_contour)# 计算凸包的面积hull_area = cv2.contourArea(hull)# 计算最大面积轮廓的紧致度if hull_area != 0:solidity = float(max_area) / hull_areaelse:solidity = 0# 计算最大面积轮廓的边界矩形x, y, w, h = cv2.boundingRect(max_contour)# 计算边界矩形的宽高比aspect_ratio = float(w) / h# 在原始图像上绘制最大面积的轮廓cv2.drawContours(image, [max_contour], -1, (0, 255, 0), 2)# 在原始图像上绘制边界矩形cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)# 在原始图像上显示面积信息cv2.putText(image, f'Area: {max_area:.2f}', (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)# 在原始图像上显示周长信息cv2.putText(image, f'Perimeter: {perimeter:.2f}', (x, y - 30), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)# 在原始图像上显示紧致度信息cv2.putText(image, f'Solidity: {solidity:.2f}', (x, y - 50), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)# 在原始图像上显示宽高比信息cv2.putText(image, f'Aspect Ratio: {aspect_ratio:.2f}', (x, y - 70), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)# 显示原始图像和处理后的图像
cv2.imshow('Original Image', cv2.imread('example.jpg'))
cv2.imshow('Processed Image', image)# 等待按键事件
cv2.waitKey(0)# 关闭所有窗口
cv2.destroyAllWindows()

函数

  • 面积计算
    • cv2.contourArea(contour):计算当前轮廓的面积,存储在 area 变量中。
  • 周长计算
    • cv2.arcLength(contour, True):计算当前轮廓的周长,True 表示轮廓是封闭的。
  • 凸包计算
    • cv2.convexHull(contour):计算当前轮廓的凸包,凸包是指能够完全包含该轮廓的最小凸多边形。
    • cv2.contourArea(hull):计算凸包的面积,存储在 hull_area 变量中。
  • 紧致度计算
    • solidity:紧致度,定义为轮廓面积与凸包面积的比值。如果凸包面积为 0,则紧致度设为 0。
  • 边界矩形计算
    • cv2.boundingRect(contour):计算当前轮廓的最小外接矩形,返回矩形的左上角坐标 (x, y) 以及宽度 w 和高度 h
    • aspect_ratio:宽高比,即矩形宽度与高度的比值。

1. cv2.contourArea:计算轮廓的面积

  • 功能cv2.contourArea 函数用于计算给定轮廓的面积。在图像处理里,轮廓通常代表一个物体的边界,计算其面积可以帮助我们了解物体的大小。
  • 语法
area = cv2.contourArea(contour)
  • 参数
    • contour:这是一个由 cv2.findContours 函数返回的轮廓点集,通常是一个 numpy.ndarray 类型的数组,其形状为 (N, 1, 2),其中 N 是轮廓上的点数,每个点用 (x, y) 坐标表示。
  • 返回值
    • area:返回的是该轮廓所围成区域的面积,数据类型为浮点数。
  • 示例
import cv2
import numpy as np# 生成一个简单的轮廓
contour = np.array([[[0, 0]], [[0, 10]], [[10, 10]], [[10, 0]]], dtype=np.int32)
area = cv2.contourArea(contour)
print(f"轮廓面积: {area}")

2. cv2.arcLength:计算轮廓的周长

  • 功能cv2.arcLength 函数用于计算给定轮廓的周长。在某些场景下,周长也是描述物体形状的一个重要特征。
  • 语法
perimeter = cv2.arcLength(contour, closed)
  • 参数
    • contour:与 cv2.contourArea 中的 contour 参数含义相同,是由 cv2.findContours 函数返回的轮廓点集。
    • closed:这是一个布尔值,用于指定轮廓是否为封闭的。如果轮廓是封闭的,应设为 True;若为开放的,则设为 False
  • 返回值
    • perimeter:返回的是轮廓的周长,数据类型为浮点数。
  • 示例
import cv2
import numpy as np# 生成一个简单的轮廓
contour = np.array([[[0, 0]], [[0, 10]], [[10, 10]], [[10, 0]]], dtype=np.int32)
perimeter = cv2.arcLength(contour, True)
print(f"轮廓周长: {perimeter}")

3. cv2.convexHull:计算轮廓的凸包

  • 功能cv2.convexHull 函数用于计算给定轮廓的凸包。凸包是指能够完全包含该轮廓的最小凸多边形。在处理不规则形状的物体时,凸包可以帮助我们简化物体的形状表示。
  • 语法
hull = cv2.convexHull(points, clockwise=None, returnPoints=None)
  • 参数
    • points:这是输入的轮廓点集,同样是由 cv2.findContours 函数返回的轮廓点集。
    • clockwise:这是一个可选的布尔值参数,用于指定凸包的点顺序。若为 True,凸包的点将按顺时针方向排列;若为 False 或省略该参数,则按逆时针方向排列。
    • returnPoints:这也是一个可选的布尔值参数。若为 True(默认值),返回的是凸包上点的坐标;若为 False,返回的是凸包上点在输入轮廓点集中的索引。
  • 返回值
    • hull:返回的是凸包的点集,是一个 numpy.ndarray 类型的数组。
  • 示例
import cv2
import numpy as np# 生成一个简单的轮廓
contour = np.array([[[0, 0]], [[0, 10]], [[10, 10]], [[10, 0]]], dtype=np.int32)
hull = cv2.convexHull(contour)
print("凸包点集:", hull)

4. 再次使用 cv2.contourArea 计算凸包的面积

在得到轮廓的凸包后,我们可以再次使用 cv2.contourArea 函数来计算凸包的面积。具体操作是将 cv2.convexHull 返回的凸包点集作为参数传入 cv2.contourArea 函数。

  • 示例
import cv2
import numpy as np# 生成一个简单的轮廓
contour = np.array([[[0, 0]], [[0, 10]], [[10, 10]], [[10, 0]]], dtype=np.int32)
hull = cv2.convexHull(contour)
hull_area = cv2.contourArea(hull)
print(f"凸包面积: {hull_area}")

5. 计算轮廓的紧致度(面积与凸包面积的比值)

紧致度是一个描述轮廓形状紧凑程度的指标,它通过轮廓的面积与凸包的面积之比来计算。如果紧致度接近 1,说明轮廓形状接近凸多边形;若紧致度远小于 1,则表示轮廓形状较为复杂,有较多的凹陷。

  • 示例
import cv2
import numpy as np# 生成一个简单的轮廓
contour = np.array([[[0, 0]], [[0, 10]], [[10, 10]], [[10, 0]]], dtype=np.int32)
area = cv2.contourArea(contour)
hull = cv2.convexHull(contour)
hull_area = cv2.contourArea(hull)
if hull_area != 0:solidity = float(area) / hull_area
else:solidity = 0
print(f"轮廓紧致度: {solidity}")

6. cv2.boundingRect:计算轮廓的边界矩形

  • 功能cv2.boundingRect 函数用于计算给定轮廓的最小外接矩形。这个矩形是与坐标轴平行的,在很多场景下,它可以为我们提供物体大致的位置和尺寸信息。
  • 语法
x, y, w, h = cv2.boundingRect(contour)
  • 参数
    • contour:同样是由 cv2.findContours 函数返回的轮廓点集。
  • 返回值
    • xy:表示边界矩形左上角顶点的坐标。
    • wh:分别表示边界矩形的宽度和高度。
  • 示例
import cv2
import numpy as np# 生成一个简单的轮廓
contour = np.array([[[0, 0]], [[0, 10]], [[10, 10]], [[10, 0]]], dtype=np.int32)
x, y, w, h = cv2.boundingRect(contour)
print(f"边界矩形: 左上角坐标 ({x}, {y}), 宽度 {w}, 高度 {h}")
http://www.xdnf.cn/news/657.html

相关文章:

  • Linux 常用命令 -pkill【通过进程名或其他属性来发送信号给一个或多个进程】
  • Transfomer的本质
  • Go语言--语法基础4--基本数据类型--浮点数类型
  • AWS EC2完全指南:如何快速搭建高性能云服务器?
  • A2A协议详解:打造统一的AI代理通信标准,实现多Agent系统协同
  • TDengine 性能监控与调优实战指南(一)
  • SQL注入 02
  • 【Part 2安卓原生360°VR播放器开发实战】第一节|通过传感器实现VR的3DOF效果
  • SpringBoot编写单元测试
  • libdxfrw库使用总结
  • 开源的 PDF 文件翻译软件
  • 借助 OpenCV 和 PyTorch 库,利用卷积神经网络提取图像边缘特征
  • 【源码+文档+调试讲解】扶贫助农系统
  • VSCode PIO使用Jlink SWD烧录Stm32
  • 【C++】初始化列表
  • 信息系统项目管理工程师备考计算类真题讲解五
  • Redis ④-通用命令
  • 解决Docker 配置 daemon.json文件后无法生效
  • 【数据可视化-19】智能手机用户行为可视化分析
  • Windows 环境下安装 MariaDB 及 HeidiSQL 使用教程
  • 玩机搞机基本常识-------小米OLED屏幕机型怎么设置为永不休眠_手机不息屏_保持亮屏功能 拒绝“烧屏” ?
  • 【Vim】vim的简单使用
  • 小迪第10天http/s数据包
  • JavaScript 一维数组转二维数组
  • 修改PointLIO项目
  • STM32配置系统时钟
  • 【PyTorch】训练时跟OOM相关的提示信息
  • AI大模型之模型幻觉
  • 【HarmonyOS 5】makeObserved接口详解
  • Java表达式1.0