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

RV1126 NO.38:OPENCV查找图形轮廓重要API讲解

在OpenCV中,图像形状识别是一项基础且实用的功能,广泛应用于计算机视觉领域的目标检测和图像分割等任务。通常通过Canny边缘检测、findContours轮廓提取和drawContours轮廓绘制这三个函数的组合使用,可以实现有效的形状检测。

一.重要的函数讲解:

1.1.findContours函数的简介以及定义

OpenCV中常用findContours函数来检测图像轮廓,这是处理轮廓的核心函数之一。该函数主要用于在二值图像中定位所有物体的轮廓。其工作原理是通过扫描二值图像,检测所有轮廓并将数据存储在向量中。以下是findContours函数的定义:

CV_EXPORTS_W void findContours( InputOutputArray image, OutputArrayOfArrays contours,OutputArray hierarchy, int mode,int method, Point offset = Point());

参数说明:

  1. image
    输入的二值图像,通常用于边缘检测、阈值处理等操作。

  2. contours
    输出的轮廓集合,每个轮廓由一系列点组成,通常采用 vector<vector<Point>> 格式存储。

  3. hierarchy(可选参数)
    输出的轮廓层次结构,用于描述轮廓间的父子关系,通常以 vector<Vec4i> 格式表示。

    对于第i个轮廓:

    • hierarchy[i][0]:同层级的下一个轮廓索引(Next)
    • hierarchy[i][1]:同层级的前一个轮廓索引(Previous)
    • hierarchy[i][2]:第一个子轮廓索引(First_Child)
    • hierarchy[i][3]:父轮廓索引(Parent)

    若某轮廓不存在对应关系(如没有下一个轮廓或父轮廓),相应索引值为负数。

Next:表示同一级别的下一个轮廓索引,若我们图片中取出轮廓0,同一水平的下一个是轮廓1。所以说当轮廓 == 0的时候,NEXT就是轮廓1。

Previous:表示同一级别的上一个轮廓索引,如轮廓1的同一级别的上一个是轮廓0。以此类推,轮廓2的上一个轮廓是轮廓1。

First_Child:表示的是当前轮廓的第一个子轮廓的索引。比方说,对于轮廓2,子轮廓是2a,所以轮廓2的First_Child是轮廓2a相对应的索引值。而对于3a来说,它有两个轮廓分别是6,7, 但这里只能取第一个轮廓,所以这里是6。

Parent:表示的是当前轮廓的父轮廓索引,比方说对于轮廓6和轮廓7来说,它们的父轮廓都是3a。

第四个参数:mode轮廓检索模式,通常有以下选项,分别是:RETR_EXTERNAL(只检测最外层轮廓)、RETR_LIST(检测所有轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,都是独立的)、RETR_CCOMP(检测所有轮廓,但是所有的轮廓只建立两个等级关系,也就是外围是顶层,而外围内的内部轮廓都属于顶层)、RETR_TREE(检测所有轮廓并建立轮廓树,这个模式下外围轮廓包含内层轮廓,内层还可以继续嵌套)。

第五个参数:method轮廓近似方法,通常有以下的几种方法,分别是CHAIN_APPROX_NONE(存储所有顶点,意思就是原封不动的把图形还原出来)、CHAIN_APPROX_SIMPLE(仅存储轮廓的拐点信息,并把所有轮廓拐点处的点保存到向量里面)、CHAIN_APPROX_TC89_L1(使用TEH_CHAIN近似算法)。

第六个参数:offset轮廓点偏移量,默认(0,0)

​​​​​​​1.2drawContours函数的简介以及定义

在OPENCV中drawContours常用于绘制图像的轮廓,如上图,我们来看看这个函数的API定义:

CV_EXPORTS_W void drawContours( InputOutputArray image, InputArrayOfArrays contours,int contourIdx, const Scalar& color,int thickness = 1, int lineType = LINE_8,InputArray hierarchy = noArray(),int maxLevel = INT_MAX, Point offset = Point() );

第一个参数:image输出图像,即绘制轮廓后的图像

第二个参数:contours轮廓的集合,它是由一系列的点组成

第三个参数:contourIdx、轮廓索引数组,指定要绘制哪些轮廓

第四个参数:contourColor,轮廓颜色,使用Scalar类型表示

第五个参数:thickness,轮廓线宽,默认1

第六个参数:lineType 轮廓线类型,默认为LINE_8

//! type of line
enum LineTypes{
FILLED=-1,
LINE_4=4,//!< 4-connected line
LINE_8,//!< 8-connected line
LINE_AA = 16 //!< antialiased line
};

第七个参数:hierarchy 轮廓层次结构,用于绘制轮廓的父子关系。默认为noArray()

第八个参数:maxLevel 表示绘制轮廓的最大层级数量若maxLevel 为0,则只绘制指定的轮廓;若maxLevel 为1,则绘制轮廓极其所有嵌套轮廓;若maxLevel 为2,则绘制轮廓、所有嵌套轮廓、所有嵌套到嵌套的轮廓。

第九个参数:轮廓点的偏移量,默认为(0,0)

​​​​​​​1.3.Canny函数的简介以及定义

Canny函数是OpenCV中用于边缘检测的核心算法,其功能如(上图一)所示。作为OpenCV中最精确高效的边缘检测方法,它能有效提取图像边缘特征。

Canny边缘检测主要包含以下关键步骤:

  1. 高斯滤波:先将图像转为灰度图,通过高斯模糊平滑图像以提高检测准确率
  2. 梯度计算:利用Sobel算子计算每个像素的梯度强度和方向,强度反映边缘强度,方向指示边缘走向
  3. 非极大抑制(NMS):过滤非边缘像素点,保留真实边缘
  4. 双阈值处理:设置高低阈值,高于高阈值的边缘被保留
  5. 边缘连接:最终连接所有强边缘,抑制弱边缘,形成完整边缘结构

具体流程如下图2所示。

下面是双阈值的处理的图解:当梯度值大于maxVal则认为是强边界;当minVal < 梯度值 < maxVal跟边界有连接的部分则保留,否则废弃;梯度值< minVal则废弃。另外需要注意的是高阈值与低阈值的比例最好是2:13:1之间。

下面我们来看看Canny的函数定义:

CV_EXPORTS_W void Canny( InputArray image, OutputArray edges,double threshold1, double threshold2,int apertureSize = 3, bool L2gradient = false );

第一个参数:image输入的图像,这个图像一定要单通道灰度图

第二个参数:edges输出的边缘图像,这个图像也必须是单通道黑白图

第三个参数:threshold1第一个滞后性阈值,低阈值,小于低阈值则认为是弱边缘,就是需要抛弃的边缘。

第四个参数:threshold2第二个滞后性阈值,高阈值,大于高阈值被认为强边缘,需要保留的边缘

第五个参数:apertureSize指的是Sobel算子大小,这个值默认为3,代表的是3*3的矩阵大小。

第六个参数:L2gradient是计算图像梯度幅度值的情况,这个值默认为False;若选择True,则使用更精确的L2范数进行计算

个人疑问点:

vector<vector<Point>> contours; 和 vector<Vec4i> hierarchy; 基于C++标准模板库(STL)的容器定义在这里的具体详述:

vector<vector<Point>> contours;

  • 结构解析
    • 外层vector:动态数组容器,存储多个内层vector
    • 内层vector<Point>:每个内层vector是一个点的集合,表示单个轮廓的所有边界点。
    • Point类型:OpenCV中的基础数据类型(cv::Point),表示二维坐标点(x, y),通常为整数类型(如int)。
  • 作用
    • contours 存储检测到的所有轮廓,每个轮廓由一组有序的边界点(Point)构成。
    • 例如:若检测到3个轮廓,则contours包含3个vector<Point>元素,每个元素对应一个轮廓的点集。
  • 模板特性
    • vector 是STL中的模板类,通过尖括号<>指定存储的数据类型(此处为vector<Point>)。
    • 嵌套模板vector<vector<Point>>形成二维动态数组,类似“数组的数组”。

2. vector<Vec4i> hierarchy;

  • 结构解析
    • Vec4i类型:OpenCV自定义的四元素整型向量cv::Vec4i),存储4个int类型数据。
    • vector<Vec4i>:动态数组,每个元素是一个Vec4i对象,表示轮廓的层次关系信息
  • 作用
    • hierarchy 存储轮廓之间的嵌套关系(如父子轮廓、兄弟轮廓等)。
    • 每个Vec4i元素包含4个整数,通常表示:
      • [Next, Previous, FirstChild, Parent]:当前轮廓的下一个轮廓索引、上一个轮廓索引、第一个子轮廓索引、父轮廓索引。
    • 例如:若轮廓A包含子轮廓B和C,则B和C的Parent索引指向A,形成层次树结构。
  • 模板特性
    • vector 同样作为模板容器,存储Vec4i类型数据。
    • Vec4i 是OpenCV对固定大小向量的模板实现(如cv::Vec<int, 4>)。

3. 为什么这样设计?

  • 轮廓检测需求
    • 轮廓(Contour)本质是点集序列,需动态存储不同数量的点(故用vector<Point>)。
    • 多个轮廓需统一管理(故用外层vector)。
    • 层次关系需结构化存储(故用Vec4i编码索引关系)。
  • STL与OpenCV结合
    • STL的vector提供动态数组能力,适配轮廓点数不确定的场景。
    • OpenCV的PointVec4i是专门为图像处理优化的数据类型,与OpenCV算法(如findContours)无缝衔接。

http://www.dtcms.com/a/572608.html

相关文章:

  • 腾讯WAIC发布“1+3+N”AI全景图:混元3D世界模型开源,具身智能平台Tairos亮相
  • 各种开源闭源大模型,包括自己本地部署的一些8b 14b模型,支持函数调用(功能调用)function call吗?
  • Spring Boot 深度剖析:从虚拟线程到声明式 HTTP 客户端,再到云原生最优解
  • 创新的商城网站建设网站页面怎么设计
  • 2016年网站建设总结php网站开发工资多少
  • 线程3.1
  • Kubernetes基础概念和命令
  • 技术干货-MYSQL数据类型详解
  • 备份工具:rsync、Tar、Borg、Veeam 备份与恢复方案
  • 深入 Pinia 工作原理:响应式核心、持久化机制与缓存策略
  • 【前端】动态插入并渲染大量数据的方法-时间分片:使用requestAnimationFrame+DocumentFragment
  • 耶鲁大学Hello Robot研究解读:人类反馈策略的多样性与有效性
  • Unity摄像机鼠标右键旋转功能
  • Spring AI Alibaba文生图实战:从零开始编写AI图片生成Demo
  • 文本编辑器做网站国外设计师
  • 网站多久电子信息工程就业方向
  • 大连网站seo顾问企业开发网站公司
  • 南京网站设计搭建公司网站怎么做rss
  • 外包做网站谷歌seo优化
  • 博物馆网站 建设方案外贸短视频营销
  • 网站如何在360做提交微信开发公司怎么样
  • 广州微网站建设信息设计图案大全
  • 苏州吴中区专业做网站郑州哪里可以做网站
  • cms网站开发毕设简述网站建设的方法
  • 怎样建立网站挣钱网站建设功能选择表
  • 郑州加盟做网站开源程序网站
  • 万维网网站注册网站线下推广怎么做
  • 郑州 网站建设:网站开发页面大小适应屏幕
  • 网络营销网站建设知识南通关键词优化软件
  • 公司网站页脚dedecms手机网站模板