图像预处理 Tricks【1】:Contours

这篇具有很好参考价值的文章主要介绍了图像预处理 Tricks【1】:Contours。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章目录



前言

轮廓可以简单地理解为连接所有连续点(沿物体边界)的曲线,这些点通常具有相同的颜色或强度。 轮廓在图像分析中具有重要意义,是物体形状分析和对象检测和识别的有用工具,是理解图像语义信息的重要依据。

本文主要介绍了在 opencv 中,一些重要的用于处理物体轮廓的方法。


1. cv2.findContours()

1.1. 方法概述

cv2.findContours() 函数是 OpenCV 库的一部分,它被广泛用于计算机视觉任务。这个函数用于检测和寻找图像中的轮廓(边界)。

通常,为了提高物体轮廓检测的准确率,首先要将彩色图像或者灰度图像处理成二值图像(灰度图)或者使用 Canny 边缘检测算法对原图像进行一次滤波处理,这样可以在不丢失轮廓信息的前提下降低图像语义信息的复杂度,更有助于我们准确地分析物体轮廓。

简而言之,寻找轮廓的过程更像是在黑色的背景中,寻找白色物体边界的过程。

1.2. cv2.findContours()

contours, hierarchy = cv2.findContours(image, mode, method)
  • 参数含义
    • imgae:单通道二值图像,白色是前景(二值图像或经过Canny算法处理之后的图像)
    • mode:轮廓检索模式
    • method:轮廓逼近方法
  • 返回值含义
    • contours
      • 一个包含了图像中所有轮廓的list对象。其中每一个独立的轮廓信息以边界点坐标 ( x , y ) (x, y) (x,y) 的形式储存在 numpy 数组中
      • [1, 712, 1, 2]
        • contours.shape[0]:这代表了在图像中发现的轮廓线的总数
        • contours[i].shape[0]:这代表第 i i i 个轮廓的点的数量;每个轮廓线由多个点组成,这个维度给出了轮廓线的长度
        • contours[i].shape[1] :这代表用于表示轮廓线中每个点的维度(坐标)的数量;在大多数情况下,这将是 2 2 2,表示每个点的 ( x , y ) (x, y) (x,y) 坐标
    • hierarchy
      • 一个包含有关轮廓层级的 4 个值的数组 [Next, Previous, First Child, Parent]
        • Next:与当前轮廓处于同一层级的下一条轮廓
        • Previous:与当前轮廓处于同一层级的上一条轮廓
        • First_Child:当前轮廓的第一条子轮廓
        • Parent:当前轮廓的父轮廓

1.2.1. 轮廓检索模式

轮廓检索模式的详细概念如下所示:

轮廓检索模式 作用
cv2.RETR_LIST 这是最简单的一种寻找方式,它不建立轮廓间的子属关系,也就是所有轮廓都属于同一层级;以 List 形式输出轮廓信息
cv2.RETR_TREE 完整建立轮廓的层级从属关系,以树结构输出轮廓信息
cv2.RETR_EXTERNAL 只寻找最高层级的轮廓,即外轮廓
cv2.RETR_CCOMP 把所有的轮廓只分为 2 个层级,不是外层的就是里层的;输出两层轮廓信息,即内外两个边界,上面一层为外边界,里面一层为内孔的边界信息

基于下面的图,来解释图像的轮廓层级:

图像预处理 Tricks【1】:Contours
图中总共有 8 条轮廓,2 和 2a 分别表示外层和里层的轮廓,3 和 3a 同理,从图中可以发现:

  1. 轮廓 0、1、2 是最外层的轮廓,我们可以说它们处于同一轮廓等级:0级
  2. 轮廓 2a 是轮廓 2 的子轮廓,反过来说 2 是 2a 的父轮廓;轮廓 2a 算一个等级:1级
  3. 同样 3 是 2a 的子轮廓,轮廓 3 处于一个等级:2级
  4. 类似的,3a 是 3 的子轮廓
  • cv2.RETR_RETR_LIST
    • 这是最简单的一种寻找方式,它不建立轮廓间的子属关系,也就是所有轮廓都属于同一层级
    • hierarchy 中的后两个值 [First_Child, Parent] 都为 − 1 -1 1
    • 因为没有从属关系,所以轮廓 0 0 0 的下一条是 1 1 1,$14 的下一条是 2 2 2
    • 如果不需要轮廓层级信息的话,更推荐使用 cv.RETR_LIST,因为性能更好
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_LIST, 2)
print(hierarchy)
# 结果如下
[[[ 1 -1 -1 -1]
  [ 2  0 -1 -1]
  [ 3  1 -1 -1]
  [ 4  2 -1 -1]
  [ 5  3 -1 -1]
  [ 6  4 -1 -1]
  [ 7  5 -1 -1]
  [-1  6 -1 -1]]]

图像预处理 Tricks【1】:Contours

  • cv2.RETR_TREE
    • Next
      • 对轮廓 0 来说,与 0 处于同一层级的下一条轮廓是 1,所以 Next = 1
      • 同理,对轮廓 1 来说,Next=2
      • 对轮廓 2 来说,没有与它同一层级的下一条轮廓了,此时 Next = -1
    • Previous
      • 对轮廓 1 来说,Previous = 0
      • 对轮廓 2 来说,Previous = 1
      • 对轮廓 2a 来说,没有上一条轮廓了,所以 Previous = -1
    • First_Child
      • 对轮廓 2 来说,第一条子轮廓就是轮廓 2a,所以 First_Child = 2a
      • 对轮廓 3 来说,First_Child = 3a
    • Parent
      • 对轮廓 2a 来说,父轮廓是 2,Parent = 2
      • 对轮廓 2 来说,没有父轮廓,Parent = 0
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, 2)
print(hierarchy)
# 结果如下
[[[ 6 -1  1 -1]
  [-1 -1  2  0]
  [-1 -1  3  0]
  [-1 -1  4  2]
  [ 5 -1 -1  3]
  [-1  4 -1  3]
  [ 7  5 -1 -1]
  [-1  6 -1 -1]]]

图像预处理 Tricks【1】:Contours

  • cv2.RETR_EXTERNAL
    • 这种方式只寻找最高层级的轮廓,也就是它只会找到前面我们所说的 3 条 0 级轮廓
contours, hierarchy = cv.findContours(thresh, cv.RETR_EXTERNAL, 2)
print(len(contours), hierarchy, sep='\n')
# 结果如下
3
[[[ 1 -1 -1 -1]
  [ 2  0 -1 -1]
  [-1  1 -1 -1]]]

图像预处理 Tricks【1】:Contours

  • cv2.RETR_CCOMP
    • 把所有的轮廓只分为 2 个层级,不是外层的就是里层
    • 上图中,括号里面 1 代表外层轮廓,2 代表里层轮廓
    • 对于轮廓 2
      • Next 就是 4,Previous 是 1
      • 它有里层的轮廓 3,所以 First_Child = 3
      • 但因为只有两个层级,它本身就是外层轮廓,所以 Parent = -1
contours, hierarchy = cv.findContours(thresh, cv.RETR_CCOMP, 2)
print(hierarchy)
# 结果如下
[[[ 1 -1 -1 -1]
  [ 2  0 -1 -1]
  [ 4  1  3 -1]
  [-1 -1 -1  2]
  [ 6  2  5 -1]
  [-1 -1 -1  4]
  [ 7  4 -1 -1]
  [-1  6 -1 -1]]]

1.2.2. 轮廓逼近方法

轮廓逼近方法 作用
cv2.CHAIN_APPROX_NONE 存储所有边界点
cv2.CHAIN_APPROX_SIMPLE 不保存轮廓中水平、垂直、对角的线段,只保存轮廓的角点
cv2.CHAIN_APPROX_TX89_L1 使用 teh-Chini 近似算法
cv2.CHAIN_APPROX_TC89_KCOS 使用 teh-Chini 近似算法
  • 一般来说,后面两种方法不常见
  • cv2.CHAIN_APPROX_NONE 见下图左;cv2.CHAIN_APPROX_SIMPLE 见下图右

图像预处理 Tricks【1】:Contours


2. cv2.drawContours()

2.1. 方法概述

在通过 cv2.findContours() 找到物体的轮廓后,有时候需要可视化物体的轮廓以判断是否符合预期,这个时候就需用到 opencv 包含的另一个重要方法 cv2.drawContours()cv2.drawContours() 可以在 image 上用指定的颜色和线的宽度画出使用 cv2.findContours() 获得的物体轮廓。

2.2. cv2.drawContours()

cv2.drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)
  • 参数含义
    • image
      • 这是要绘制轮廓线的输入图像
      • 通常是一个 RGB 格式的图像,或者是一个灰度图
    • contours
      • 是你想在图像上绘制的轮廓线的列表
      • 它应该是一个 Python 列表,其中每个轮廓被表示为一个 ( x , y ) (x, y) (x,y) 坐标的 NumPy 数组
    • contourIdx
      • 这个参数指定要画的轮廓的索引
      • 通常使用 -1 来绘制所有的轮廓
    • color
      • 这个参数指定了轮廓线的颜色
      • 对于彩色图像,颜色应该被指定为代表 BGR 值的三个整数的元组(需要注意是 BGR 而不是 RGB,与使用 cv2.imread() 方法读进来的彩色图像通道相同)
      • 对于灰度图像,颜色值是一个代表强度的标量
    • thickness
      • 这个参数指定轮廓线的厚度,单位是像素
      • 使用一个负值来填充轮廓线

3. cv2.contourArea()

3.1. 方法概述

cv2.contourArea() 函数是 OpenCV 提供的一个实用函数,用于计算一个轮廓的面积。它接受一个轮廓作为输入,并返回该轮廓的面积。

3.2. cv2.contourArea()

area = cv2.contourArea(contours, oriented=false)
  • 参数含义
    • contours
      • 要计算面积的输入轮廓
      • 应该是一个由 ( x , y ) (x, y) (x,y) 坐标组成的 NumPy 数组表示的单一轮廓
    • oriented
      • 面向区域标识符。有默认值 false
      • 若为 true,该函数返回一个带符号的面积值,正负取决于轮廓的方向(顺时针还是逆时针)
      • 若为 false,表示以绝对值返回。
  • 返回值
    • area
      • 是输出变量,用于存储计算出的轮廓所围成的面积
      • 它是一个浮点值,以像素为单位表示面积

3.3. 存在的问题

需要注意的是 cv2.contourArea() 计算得到的面积,可能会比预期的面积稍微小一点,这是因为 cv2.contourArea() 通过取连通域边界像素中心点,连接起来,成为一个轮廓,导致一周得边界像素点丢失,即求得得面积比真实得面积少了一圈

比如下图,真实面积 4 × 4 = 16 4 \times 4 = 16 4×4=16,而 cv2.contourArea() 则只计算红线内的面积,只有 3 × 3 = 9 3 \times 3 = 9 3×3=9

图像预处理 Tricks【1】:Contours

因此,cv2.contourArea() 可能将一些轮廓的面积计算为 0,如下图所示

图像预处理 Tricks【1】:Contours

一个简单的解决方法为

 rect = cv2.minAreaRect(contours)  #最小外接矩形
 box = cv2.boxPoints(rect)
 box = np.int0(box)
 area = cv2.contourArea(box)

总结

本文主要记录了一些博主最近在实验过程中遇到的与 label 轮廓相关的处理函数,如果后面有需要,会继续更新相关的函数。

参考博客
参考博客文章来源地址https://www.toymoban.com/news/detail-503241.html

到了这里,关于图像预处理 Tricks【1】:Contours的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用 SKimage 的图像预处理

    介绍 图像是视觉对象的二维表示,例如照片、绘画或素描。在数字成像中,图像存储为像素值数组,其中每个像素代表图像亮度和颜色的样本。每个像素的颜色可以由一个或多个通道表示,如传统彩色图像中的红色、绿色和蓝色 (RGB) 通道。在本文中,你将学习各种图像预处

    2024年02月03日
    浏览(54)
  • 计算机视觉(2)——图像预处理

    二、图像预处理 2.1 介绍  2.2 特征提取方法 2.2.1 直方图 2.2.2 CLAHE 2.2.3 形态学运算 2.2.4 空间域处理及其变换 2.2.5 空间域分析及变换  (1) 均值滤波 (2)中值滤波 (3)高斯滤波 (4) 梯度Prewitt滤波 (5) 梯度Sobel滤波 (6) 梯度Laplacian滤波 (7) 其他滤波  2.2.6 频域分

    2024年02月03日
    浏览(58)
  • 关于图像分割的预处理 transform

    目录 1. 介绍 2. 关于分割中的 resize 问题 3. 分割的 transform 3.1 随机缩放 RandomResize 3.2 随机水平翻转 RandomHorizontalFlip 3.3 随机竖直翻转 RandomVerticalFlip 3.4 随机裁剪 RandomCrop 3.5 ToTensor 3.6 normalization 3.7 Compose 3.8 中心裁剪 3.9 Resize 缩放 4. 预处理结果可视化 图像分割的预处理不像

    2024年02月04日
    浏览(49)
  • 【CV学习笔记】图像预处理warpaffine

    在学习图像预处理的时候发现,之前用的图像预处理方法一般为 resize和letter box,这两种方法比较低效,后来在手写AI中接触到了warpaffine,只需要一步就能够对图像进行预处理,同时还能很方便的进行cuda加速,于是便记录下来。 欢迎正在学习或者想学的CV的同学进群一起讨论与

    2023年04月08日
    浏览(46)
  • 【Computer Vision】图像数据预处理详解

    活动地址:[CSDN21天学习挑战赛](https://marketing.csdn.net/p/bdabfb52c5d56532133df2adc1a728fd) 作者简介 :在校大学生一枚,华为云享专家,阿里云星级博主,腾云先锋(TDP)成员,云曦智划项目总负责人,全国高等学校计算机教学与产业实践资源建设专家委员会(TIPCC)志愿者,以及编程

    2024年02月06日
    浏览(48)
  • OpenCV图像预处理常用函数及流程

    在PyCharm终端中,运行如下命令 由于默认使用的为外网资源,下载速度和稳定性较差,具体看网络状态。如下命令为使用清华镜像下载安装相应的包 在终端中运行命令时,Windows10系统可能会存在如下报错:无法加载激活文件,因此在此系统上禁止运行脚本。此情况是因为win

    2024年02月05日
    浏览(50)
  • C++系列九:预处理功能

    预处理器是 C++ 编译器提供的一个工具,允许程序员在编译之前对源代码文件做出修改。它主要是根据在代码中命名实体的定义(如宏、条件编译指令)、源文件调用等操作指令,生成一个新的源代码文件,以交给编译器进行编译。预处理器通常会将 # 开头的指令与代码区别

    2024年02月04日
    浏览(36)
  • Pytorch学习笔记(3):图像的预处理(transforms)

      目录  一、torchvision:计算机视觉工具包  二、transforms的运行机制 (1)torchvision.transforms:常用的图像预处理方法 (2)transforms运行原理   三、数据标准化 transforms.Normalize() 四、数据增强  4.1 transforms—数据裁剪 (1)transforms.CentorCrop (2)transforms.RandomCrop (3)RandomResiz

    2023年04月13日
    浏览(43)
  • 医学nii图像 预处理——图像裁剪 重采样 灰度区域 归一化 修改图像尺寸

    鄙人主要研究方向为医学图像配准,在使用CT数据集之前需要对数据进行预处理。 常规预处理步骤:(*代表本代码有) 1. 裁剪出ROI区域 。 目的:减小图像尺寸,减小内存消耗,减小无关信息,可提高实验精度 2. 重采样 。 一般会重采样到各向同性,例如,将图像重采样到每体

    2024年02月12日
    浏览(42)
  • 【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割7(数据预处理)

    在上一节:【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割6(数据预处理) 中,我们已经得到了与 mhd 图像同 seriesUID 名称的 mask nrrd 数据文件了,可以说是一一对应了。 并且, mask 的文件,还根据结节被多少人同时标注,区分成了4个文件夹,分别是标注了一、二、三、四次,

    2024年02月07日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包