opencv#33 边缘检测

边缘检测原理

     图像的每一行每一列都可以看成是一个连续的信号经过离散后得到的数值,例如上图左侧给出的图像由黑色到白色的一个信号,也就是图像中某一行像素变化是由黑色逐渐到白色,我们将其对应在一个坐标轴中,将像素值的大小对应与我们y轴,我们可以得到中间图片的曲线,曲线就表示这图像某一行像素灰度值的变化关系,当我们对此曲线求导,就可以得到最下面图片的曲线,图像的边缘就是图像中像素灰度值发生变化的像素点的集合,通过计算函数导数的方式可以找到灰度值变化的点,导数值大说明灰度值变化大,导数值为0,说明灰度值没有变化。图像边缘就是对于灰度函数图像中函数值发生突然改变的区域(点的集合)。

      导数(梯度)是微分中的概念,而微分针对的是连续可导的函数,但我们图像是离散的函数,因此对应着差分。微分差分核心思想一致,我们在边缘检测的过程中运用微分的思想来指导,但在实际操作中,我们用差分的形式来实现边缘检测。

      我们计算梯度(导数)时,通常采用差分值来表示导数,差分值就是两个像素的差值,由于梯度对于图像信号来说是一个相对的概念,也就是如果每一个梯度都乘或除以2是没有任何区别的,因此这里我们直接相减就可以。两个像素间的梯度对应在图像中没有意义,因此我们改进的想法是,若有三个像素,第三个像素减去第一个像素除以两者之间的距离,得到的就是第二个像素的梯度,通过这样的方式实现了梯度与像素相对应的方式。

Sobel算子边缘检测

Sobel()

void cv::Sobel(InputArray    src,OutputArray   dst,int           ddepth,int           dx,int           dy,int           ksize = 3,double        scale = 1,double        delta = 0,int           borderType = BORDER_DEFAULT)

·src:待边缘检测图像。

·dst:边缘检测后图像,与输入图像具有相同的尺寸和通道数。

·ddepth:边缘检测后,输出图像的数据类型,由于像素的变化不规律,因此我们用后一时刻的像素减去前一时刻的像素,两个像素的大小未知,可能会出现负值,所以不推荐使用八位无符号整数8U,我们可以使用16S。

·dx,dy:进行索贝尔算子时对于边缘检测的梯度的阶次。

·ksize:使用边缘检测时算子的尺寸大小,默认值为3.

·scale,delta:卷积过程中,对结果进行缩放的系数以及偏移量。例如图像变化平缓,那么得到的系数可能就比较小,直接乘这个系数就可以将梯度扩大,scale默认值为1,也就是不对结果进行缩放,delta默认值为0,也就是不对结果进行偏移。

·borderType:图像外扩标志。

     进行索贝尔边缘检测时,常见的方法是先进行行检测,再进行列检测,也就是对x和y方向分别求导。而在图像的每一点,结合上面求出的导数值,利用勾股定理求出近似梯度,或者是为了提高效率,使用不开平方的近似:利用x和y方向的导数的绝对值之和求出图像每一点的近似值的绝对值。这样可以实现对于图像整体的边缘检测。

     索贝尔算子为了增加梯度的大小,允许计算时三行同时进行计算,例如上图x方向的计算,是有一个主要的计算行(比如中间行),上下两行作为辅助计算,主要行所占权重较大,辅助行所占权重较小,y方向计算也是一样的,对y行进行转置,就可以得到y方向上边缘检测的边缘检测算子。

Scharr算子边缘检测

Scharr()

void cv::Scharr(InputArray    src,OutputArray   dst,int           ddepth,int           dx,int           dy,double        scale = 1,double        delta = 0,int           borderType = BORDER_DEFAULT)

Scharr算子就是在原先索贝尔算子的基础上对边缘检测的结果进一步加强。也就是得到的边缘响应更强了。

x方向的算子其实就是在索贝尔算子的基础上调整了每一个位置的系数,将主要行设置成10,将辅助行设置成3,这样可以得到一个较大的响应,但坏处是比较微弱的边缘通过此算子计算也会得到较强的响应。对于x方向算子进行转置,我们也可以得到y方向的算子。

两种算子的生成

getDerivKernels()

上面两种算子的函数内部也是调用了此函数。

void cv::getDerivKernels(OutputArray    kx,OutputArray    ky,int            dx,int            dy,int            ksize,normalize = bool           false,int            ktype = cv_32F)

·kx:行滤波器系数的输出矩阵,尺寸为ksize*1。

·ky:列滤波器系数的输出矩阵,尺寸为ksize*1。

·dx:X方向导数的阶次。

·dy:y方向导数的阶次。

·ksize:滤波器的大小,可以选择的参数为FILTER_SCHARR(得到的就是Scharr算子),1,3,5,或7(可设定为索贝尔算子)。

·normalize:是否对滤波器系数进行归一化的标志,默认值为false,表示不进行归一化。上面的Sobel算子和Scharr算子都没有进行归一化,可能会使得边缘梯度响应特别大。

·ktype:滤波器系数类型,可以选择CV_32F或CV_64F,默认参数是CV_32F。

这里需要说明一点:当我们选择Sobel算子时,梯度阶数dx,dy <= 尺寸;Scharr算子的dx+dy <= 1。

通过这样的形式规定了结束与算子种类以及尺寸的关系,当我们求取过高的阶数,而采用较小的尺寸,这样是没办法实现过高阶数的求取的。

示例
#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv; //opencv的命名空间
using namespace std;//主函数
int main()
{//读取图像,黑白图像边缘检测结果较为明显Mat img = imread("E:/opencv/opencv-4.6.0-vc14_vc15/opencv/lenaGray.png");if (img.empty()){cout << "请确认图像文件名称是否正确" << endl;return -1;}Mat resultX, resultY, resultXY;//X方向一阶边缘Sobel(img, resultX, CV_16S, 1, 0, 1); //尺寸参数设置为1其实是3convertScaleAbs(resultX, resultX); //求绝对值函数//Y方向一阶边缘Sobel(img, resultY, CV_16S, 0, 1, 3); //只不过将上面的dx,dy交换了,尺寸参数设置为1还是3是一致的convertScaleAbs(resultY, resultY);//整体图像的一阶边缘resultXY = resultX + resultY;//显示图像imshow("resultX", resultX);imshow("resultY", resultY);imshow("resultXY", resultXY);cout << "下面是进行Scharr边缘检测" << endl;waitKey(0);//等待函数用于显示图像,按下键盘任意键后退出//X方向一阶边缘Scharr(img, resultX, CV_16S, 1, 0);convertScaleAbs(resultX, resultX); //求绝对值函数//Y方向一阶边缘Scharr(img, resultY, CV_16S,0,1);convertScaleAbs(resultY, resultY);//整体图像的一阶边缘resultXY = resultX + resultY;//显示图像imshow("resultX", resultX);imshow("resultY", resultY);imshow("resultXY", resultXY);cout << "接下来生成边缘检测器" << endl;waitKey(0);//等待函数用于显示图像,按下键盘任意键后退出Mat sobel_x1, sobel_y1;//存放分离的Sobel算子Mat scharr_x, scharr_y;//存放分离的Scharr算子Mat sobelX1, scharrX;//存放最终算子//一阶X方向Sobel算子getDerivKernels(sobel_x1, sobel_y1, 1, 0, 3);//一阶尺寸为3sobel_x1 = sobel_x1.reshape(CV_8U, 1);sobelX1 = sobel_y1 * sobel_x1; //计算滤波器//X方向Scharr算子getDerivKernels(scharr_x, scharr_y, 1, 0, FILTER_SCHARR);scharr_x = scharr_x.reshape(CV_8U, 1);scharrX = scharr_y * scharr_x; //计算整体x方向滤波器cout << "X方向一阶Sobel算子" << endl << sobelX1 << endl;cout << "X方向Scharr算子" << endl << scharrX << endl;waitKey(0);//等待函数用于显示图像,按下键盘任意键后退出return 0;}
结果

Sobel边缘检测:

 

Scharr边缘检测:

 

 

生成的边缘检测器:

 

对于Sobel算子边缘检测的X方向,得到的边缘更多的是垂直的边缘,而Y方向,得到的边缘更多的是行方向的边缘,说明X方向和Y方向在进行检测时是各有侧重点的。将两者叠加就可以得到整幅图像的边缘。

对于Scharr算子边缘检测与Sobel是类似的,由于Scharr类型将得到的边缘梯度进行了很大的扩展,因此较小的边缘区域也被显示出来,所以得到的结果中感觉出有很多边缘,实际上它对微弱的边缘进行了扩充,可能两个像素只相差1,但是对结果扩大了很多倍,显示的就较亮,得到整体也是一个更加亮的图像。

生成的两种算子的类型,得到的结果是与上面一致。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/247094.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java基础】聊聊你不知道反射的那些事

在编程语言中&#xff0c;反射是一个绕不过的一个话题&#xff0c;反射、注解、动态代理是支撑框架运行的核心技术。 在Spring中&#xff0c;IOC利用反射实现&#xff0c;创建对象。AOP利用动态代理实现&#xff0c;实现切面编程&#xff0c;配置利用注解实现。所以继上一篇&am…

代码随想录算法训练营第32天 | 122.买卖股票的最佳时机II 55.跳跃游戏 45.跳跃游戏II

买卖股票的最佳时机II 贪心思路 要想使用贪心算法解决此问题&#xff0c;意识到利润是可分解的很关键。比如[1,2,3,4,5]这个输入&#xff0c;最大利润为第一天买入&#xff0c;第五天卖出。这等效于第一天买入&#xff0c;第二天卖出&#xff0c;第二天再买入。。。 prices[4]…

HCS-华为云Stack-FusionSphere

HCS-华为云Stack-FusionSphere FusionSphere是华为面向多行业客户推出的云操作系统解决方案。 FusionSphere基于开放的OpenStack架构&#xff0c;并针对企业云计算数据中心场景进行设计和优化&#xff0c;提供了强大的虚拟化功能和资源池管理能力、丰富的云基础服务组件和工具…

MYSQL基本查询(CURD:创建、读取、更新、删除)

文章目录 前言一、Create1.全列插入2.指定列插入3.插入否则更新4.替换 二、Retrieve1.SELECT列2.WHERE条件3.结果排序4.筛选分页结果 三、Update四、Delete1.删除数据2.截断表 五、插入查询结果六、聚合函数 前言 操作关系型数据库的编程语言&#xff0c;定义了一套操作关系型…

kali系统入侵电脑windows(win11系统)渗透测试,骇入电脑教学

本次渗透测试将使用kali虚拟机&#xff08;攻击机&#xff09;对本机&#xff08;靶机&#xff09;进行入侵并监控屏幕 声明&#xff1a;本篇仅仅是将本机作为靶机的一次简易渗透测试&#xff0c;实际情况中基本不可能出现如此简单的木马骇入&#xff08;往往在上传木马时就被防…

Android App开发-简单控件(4)——按钮触控和图像显示

3.4 按钮触控 本节介绍了按钮控件的常见用法&#xff0c;包括&#xff1a;如何设置大小写属性与点击属性&#xff0c;如何响应按钮的点击事件和长按事件&#xff0c;如何禁用按钮又该如何启用按钮&#xff0c;等等。 3.4.1 按钮控件Button 除了文本视图之外&#xff0c;按钮…

clickhouse 安装与入门(单节点安装)

1、简介 Clickhouse 是一个开源的面向联机分析处理&#xff08;OLAP, On-Line Analytical Processing&#xff09;的列式存储数据库管理系统。写入快、查询快&#xff0c;支持sql向量化、并行和分布式查询&#xff1b;但是不支持事务&#xff0c;不支持二级索引等。由俄罗斯的Y…

5_机械臂运动学基础_矩阵

上次说的向量空间是为矩阵服务的。 1、学科回顾 从科技实践中来的数学问题无非分为两类&#xff1a;一类是线性问题&#xff0c;一类是非线性问题。线性问题是研究最久、理论最完善的&#xff1b;而非线性问题则可以在一定基础上转化为线性问题求解。 线性变换&#xff1a; 数域…

【jetson笔记】解决vscode远程调试qt.qpa.xcb: could not connect to display报错

配置x11转发 jetson远程安装x11转发 安装Xming Xming下载 安装完成后打开安装目录C:\Program Files (x86)\Xming 用记事本打开X0.hosts文件&#xff0c;添加jetson IP地址 后续IP改变需要重新修改配置文件 localhost 192.168.107.57打开Xlaunch Win菜单搜索Xlaundch打开 一…

openssl3.2 - 测试程序的学习 - test\acvp_test.c

文章目录 openssl3.2 - 测试程序的学习 - test\acvp_test.c概述笔记要单步学习的测试函数备注END openssl3.2 - 测试程序的学习 - test\acvp_test.c 概述 openssl3.2 - 测试程序的学习 将test*.c 收集起来后, 就不准备看makefile和make test的日志参考了. 按照收集的.c, 按照…

【java面试】常见问题(超详细)

目录 一、java常见问题JDK和JRE的区别是什么&#xff1f;Java中的String类是可变的还是不可变的&#xff1f;Java中的equals方法和hashCode方法有什么关系&#xff1f;Java中什么是重载【Overloading】&#xff1f;什么是覆盖【Overriding】&#xff1f;它们有什么区别&#xf…

【计算机网络】概述|分层体系结构|OSI参考模型|TCP/IP参考模型|网络协议、层次、接口

目录 一、思维导图 二、计算机网络概述 1.计算机网络定义、组成、功能 2.计算机网络分类 3.计算机网络发展历史 &#xff08;1&#xff09;计算机网络发展历史1&#xff1a;ARPANET->互联网 &#xff08;2&#xff09;计算机网络发展历史2&#xff1a;三级结构因特网 …

【JavaWeb】日程管理系统 添加过滤器登录校验 第三期

文章目录 过滤器控制登录校验创建过滤器类修改login原业务方法 总结 过滤器控制登录校验 未添加过滤器 可以直接访问 showShedule.html 需求说明: 未登录状态下不允许访问showShedule.html和SysScheduleController相关增删改处理,重定向到login.html,登录成功后可以自由访问 创…

RabbitMQ进阶篇【理解➕应用】

&#x1f973;&#x1f973;Welcome 的Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于RabbitMQ的相关操作吧 目录 &#x1f973;&#x1f973;Welcome 的Huihuis Code World ! !&#x1f973;&#x1f973; 一.什么是交换机 1.概念释义 2.例…

web前端-------伪类和伪元素

但是&#xff0c;网页中一些特殊的样式&#xff0c;需要用到特殊的CSS选择器来设置。&#xfeff;在CSS中&#xff0c;我们把这类选择器称为伪选择器。 伪选择器&#xff0c;分为伪类选择&#xfeff;器和伪元素选择器两个大类。 伪类选择器&#xff0c;简称伪类&#xff1b;…

【贪吃蛇:C语言实现】

文章目录 前言1.了解Win32API相关知识1.1什么是Win32API1.2设置控制台的大小、名称1.3控制台上的光标1.4 GetStdHandle&#xff08;获得控制台信息&#xff09;1.5 SetConsoleCursorPosition&#xff08;设置光标位置&#xff09;1.6 GetConsoleCursorInfo&#xff08;获得光标…

【DeepLearning-8】MobileViT模块配置

完整代码&#xff1a; import torch import torch.nn as nn from einops import rearrange def conv_1x1_bn(inp, oup):return nn.Sequential(nn.Conv2d(inp, oup, 1, 1, 0, biasFalse),nn.BatchNorm2d(oup),nn.SiLU()) def conv_nxn_bn(inp, oup, kernal_size3, stride1):re…

接口测试入门,如何划分接口文档

1.首先最主要的就是要分析接口测试文档&#xff0c;每一个公司的测试文档都是不一样的。具体的就要根据自己公司的接口而定&#xff0c;里面缺少的内容自己需要与开发进行确认。 我认为一针对于测试而言的主要的接口测试文档应该包含的内容分为以下几个方面。 a.具体的一个业…

一文深度解读多模态大模型视频检索技术的实现与使用

当视频检索叠上大模型Buff。 万乐乐&#xff5c;技术作者 视频检索&#xff0c;俗称“找片儿”&#xff0c;即通过输入一段文本&#xff0c;找出最符合该文本描述的视频。 随着视频社会化趋势以及各类视频平台的快速兴起与发展&#xff0c;「视频检索」越来越成为用户和视频平…

JVM/GC复习

JVM/GC JVM(java虚拟机)MATjstack(将正在运行的JVM的线程进行快照并且打印出来)死锁VisualVM工具(监控线程内存使用情况)JMX分析堆日志什么情况下可能需要JVM调优补充JVM内部结构JVM 调优策略(补充) GC垃圾回收算法1.引用计数法2.标记清除发3.标记压缩算法4.复制算法5.分代算法…