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

4.RV1126-OPENCV 图像轮廓识别

一.图像识别API

1.图像识别作用

        它常用于视觉任务、目标检测、图像分割等等。在 OPENCV 中通常使用 Canny
函数、findContours 函数、drawContours 函数
结合在一起去做轮廓的形检测。

2.常用的API 

  • findContours 函数:用于寻找图片的轮廓,并把所有的数据存储在向量里面                    

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

    第一个参数:image 输入的二值图像,这个图像通常是用在边缘检测、阈值处理等等
    第二个参数:contours 输出的轮廓集合,每一个轮廓都是由点组成,通常用vector<vector<Point>>来表示

    第三个参数:hierarchy 输出的轮廓层次结构,这通常表示轮廓之间的父子关系,这个是可选参数,通常用 vector<Vec4i> hierarchy来表示。比方说,第 i 个轮廓,hierarchy[i][0]、hierarchy[i][1]、hierarchy[i][2]、hierarchy[i][3], 依次为第 i 个轮廓[Next、Pervious、First_Child,Parent], 这表示的是相同等级下的下一轮廓、前一轮廓,第一个子轮廓和父轮廓的索引号。若轮廓 i 没有下一个,前一个或者父级轮廓,则层次相应的元素是负数。如下图:

    第四个参数: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)

    • drawContours 函数:用于绘制图像的轮廓,配合findContours 函数使用,用findContours 函数获取轮廓,用drawContours 函数画轮廓。

             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

    第七个参数:hierarchy ,轮廓层次结构,用于绘制轮廓的父子关系。默认为 noArray()
    第八个参数:maxLevel ,表示绘制轮廓的最大层级数量。若 maxLevel 为 0,则只绘制指定的轮廓;若 maxLevel 为 1,则绘制轮廓极其所有嵌套轮廓;若 maxLevel 为 2,则绘制轮廓、所有嵌套轮廓、所有嵌套到嵌套的轮廓。
    第九个参数:轮廓点的偏移量,默认为(0,0) 

    • Canny 函数:用于边缘检测计算。效果如下:

             工作原理:就是一系类数学处理方法。高斯滤波(将图像转换为灰度图像,高斯滤波作用是平滑图像,让 Canny 检测的时候准确率更高)、梯度强度和方向的计算(计算图像中每个像素的强度和方向、强度表示像素点的边缘强度、梯度表示的是边缘方向这里的梯度需要用到 sobel 因子)、非极大抑制(经过 NMS 操作后,会除去一些不是边缘的像素点)、双阈值处理(给出一个阈值,若超过这个阈值的边缘则会被保留)、边缘链接(经过双阈值处理过后,强边缘则会留下来,弱边缘则会被抑制,并会把所有的强边缘全部连接起来)。

             工作原理白话文:把3通道图片(也就是彩色图片)转化成双通道图片(也就是灰色图像),然后用高斯滤波去除细小杂物让它更好识别轮廓;梯度强度和方向的计算,就是不同程度扫描轮廓,扫描很多轮廓;非极大抑制,去除边边角角不是边缘的像素点;双阈值处理,就是在之前扫描不同程度轮廓上设置两个阈值(Max,Min),大于Max值被认为是轮廓保留下来,小于Min被认为不是轮廓去除掉,在两值中间的是边缘保留,不是去掉;边缘链接,就是一个完整轮廓。

            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 范数进行计算

    二. 代码实战扫描物体轮廓

    1.扫描轮廓步骤

            分别是 imread 读取图片(这个图片默认是 3 通道)、利用 cvtColor 把 8VU3 的三通道图片转换成灰度图(8VU1)、调用 Canny 对灰度图像进行边缘检测、调用 findContours 去查找轮廓、循环轮廓数量然后调用 drawContours 进行画框操作。

    2.代码

    #include <opencv2/opencv.hpp>
    #include <opencv2/dnn.hpp>
    #include <opencv2/imgcodecs.hpp>
    #include <opencv2/imgproc.hpp>
    #include <iostream>using namespace cv;
    using namespace std;int main()
    {//读取图片Mat img = imread("zjl.jpg");//彩色图片转化灰度图片Mat imgGray;cvtColor(img, imgGray, COLOR_RGB2GRAY);//灰度图片边缘检测轮廓Mat imgCanny;Canny(imgGray, imgCanny, 25, 75); //Canny对图像进行边缘检测,弱阈值25,强阈值75//查询轮廓vector<vector<Point>> contours; //定义轮廓vector<Vec4i> hierarchy; //定义层次结构findContours(imgCanny, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE); //查询轮廓,RETR_EXTERNAL表示只检测外部轮廓,CHAIN_APPROX_NONE表示存储所有的轮廓点//绘制轮廓Mat drawing = Mat::zeros(imgCanny.size(), CV_8UC3);//创建一个空白图像,用于绘制轮廓for (int i = 0; i < contours.size(); i++)   //遍历所有轮廓{Scalar color = Scalar(255, 255, 0); //随机生成颜色drawContours(drawing, contours, i, color, 1, 8, hierarchy); //对图像轮廓进行画框}//显示图像imwrite("zjl1.jpg", drawing);return 0;
    }

    3.效果

    http://www.lqws.cn/news/69553.html

    相关文章:

  1. 【SpringBoot】| 接口架构风格—RESTful
  2. 什么是 CPU 缓存模型?
  3. 深入探讨redis:缓存
  4. vue-13(延迟加载路由)
  5. Vue-6-前端框架Vue之基于Plotly.js绘制曲线
  6. 【软件测试】web自动化:Pycharm+Selenium+Firefox(一)
  7. WebSocket与Reactor模式:构建实时交互应用
  8. Qt OpenGL 实现交互功能(如鼠标、键盘操作)
  9. 【基于阿里云搭建数据仓库(离线)】Data Studio创建资源与函数
  10. [Java恶补day13] 53. 最大子数组和
  11. AI大数据模型如何与thingsboard物联网结合
  12. 基于SpringBoot运动会管理系统设计和实现(源码+文档+部署讲解)
  13. 20250602在荣品的PRO-RK3566开发板的Android13下打开关机对话框
  14. 【LeetCode 题解】两数之和(C++/Python 双解法):从语法到算法的全面解析
  15. (LeetCode 每日一题)135. 分发糖果 ( 贪心 )
  16. 基于Python学习《Head First设计模式》第三章 装饰者模式
  17. Spring Security入门:创建第一个安全REST端点项目
  18. 好用的C/C++/嵌入式 IDE: CLion的下载安装教程(保姆级教程)
  19. 黑马Java面试笔记之 微服务篇(SpringCloud)
  20. 【图论 拓扑排序 贪心 临项交换】P5603 小 C 与桌游 题解|普及+
  21. XML-BEANS compiled schema: Could not locate compiled schema resource
  22. Day43打卡(补41+42) @浙大疏锦行
  23. 123网盘SDK-npm包已发布
  24. 电脑为什么换个ip就上不了网了
  25. BiliNote部署实践
  26. postman工具使用
  27. Kotlin 中 companion object 扩展函数详解
  28. Kotlin 中companion object {} 什么时候触发
  29. 【iOS安全】使用LLDB调试iOS App | LLDB基本架构 | LLDB安装和配置
  30. Flask+LayUI开发手记(七):头像的上传及突破static目录限制