c++gdal如何在大图像中截取小图像并获取其图像信息_【图像处理】OpenCV系列十 --- 边缘检测之Canny算子...

上一篇我们学习了图像处理形态学相关知识点,相信大家学习之后已经对形态学有了足够的理解了,那么接下来,我们一起来学习一下图像处理中的边缘检测吧!我们将会重点学习边缘检测各种算子和滤波器 --- Canny算子,Sobel算子,Laplace算子以及Scharr滤波器,本篇我们将会学习Canny算子的原理与用法!

一、理论

边缘检测是图像处理和计算机视觉中的基本问题,边缘检测的目的是标识数字图像中亮度变化明显的点;图像属性中的显著变化通常反映了属性的重要事件和变化。

这些包括

(i)深度上的不连续

(ii)表面方向不连续

(iii)物质属性变化

(iv)场景照明变化

边缘检测是图像处理和计算机视觉中,尤其是特征提取中的一个研究领域。

边缘检测的一般步骤

1)滤波:边缘检测的算法主要是基于图像强度的一阶和二阶导数,但导数通常对噪声很敏感,因此必须采用滤波器来改善与噪声有关的边缘检测器的性能。常见的滤波方法主要有高斯滤波,即采用离散化的高斯函数产生一组归一化的高斯核(具体见“高斯滤波原理及其编程离散化实现方法”一文),然后基于高斯核函数对图像灰度矩阵的每一点进行加权求和;

2)增强:增强边缘的基础是确定图像各点邻域强度的变化值。增强算法可以将图像灰度点邻域强度值有显著变化的点凸显出来。在具体编程实现时,可通过计算梯度幅值来确定。

3)检测:经过增强的图像,往往邻域中有很多点的梯度值比较大,而在特定的应用中,这些点并不是我们要找的边缘点,所以应该采用某种方法来对这些点进行取舍。实际工程中,常用的方法是通过阈值化方法来检测。

二、Canny算子

Canny边缘检测算子是John F.Canny于 1986 年开发出来的一个多级边缘检测算法。更为重要的是 Canny 创立了边缘检测计算理论(Computational theory ofedge detection),解释了这项技术是如何工作的。Canny边缘检测算法以Canny的名字命名,被很多人推崇为当今最优的边缘检测的算法。

其中,Canny 的目标是找到一个最优的边缘检测算法,让我们看一下最优边缘检测的三个主要评价标准:

  • 低错误率: 标识出尽可能多的实际边缘,同时尽可能的减少噪声产生的误报;
  • 高定位性: 标识出的边缘要与图像中的实际边缘尽可能接近;
  • 最小响应: 图像中的边缘只能标识一次,并且可能存在的图像噪声不应标识为边缘。

为了满足这些要求 Canny 使用了变分法,这是一种寻找满足特定功能的函数的方法。最优检测使用四个指数函数项的和表示,但是它非常近似于高斯函数的一阶导数。

(一)Canny算子的检测步骤

1.灰度化

把彩色图像变成灰度图像,该部分是按照Canny算法通常处理的图像为灰度图,如果获取的彩色图像,那首先就得进行灰度化。以RGB格式的彩图为例,通常灰度化采用的公式是:

Gray=0.299R+0.587G+0.114B;

2、高斯滤波

对图像高斯滤波,图像高斯滤波的实现可以用两个一维高斯核分别两次加权实现,也就是先一维X方向卷积,得到的结果再一维Y方向卷积。当然也可以直接通过一个二维高斯核一次卷积实现。也就是二维卷积模板,由于水平有限,只说二维卷积模板怎么算。

3d1e58c45d30ae96b8835efb0fd101cd.png

高斯滤波

模板中每一个点的高斯系数可以由上面的公式计算,这样得到的是不是最终的模板呢?答案不是,需要归一化,也即是每一个点的系数要除以所有系数之和,这样才是最终的二维高斯模板。

这个里面有个小知识点,要想计算上面的系数,需要知道高斯函数的标准差σ (sigma),还需要知道选3x3还是5x5的模板,也就是模板要多大,实际应用的时候,这两者是有关系的,根据数理统计的知识,高斯分布的特点就是数值分布在(μ—3σ,μ+3σ)中的概率为0.9974,也就是模板的大小其实就是6σ这么大就OK了,但是6σ可能不是奇数,因为我们一定要保证有核心。所以模板窗口的大小一般采用1+2ceil(3nSigma) ceil是向上取整函数,例如ceil(0.6)=1;

计算得到模板,那就是直接卷积就OK,卷积的意思就是图像中的点附近的模板大小区域乘以高斯模板区域,得到的结果就是该点卷积后的结果。卷积的核心意义就是获取原始图像中像模板特征的性质。

3.计算梯度幅值和方向

图像的边缘可以指向不同方向,因此经典Canny算法用了四个梯度算子来分别计算水平,垂直和对角线方向的梯度。但是通常都不用四个梯度算子来分别计算四个方向。常用的边缘差分算子(如Rober,Prewitt,Sobel)计算水平和垂直方向的差分Gx和Gy。这样就可以如下计算梯度模和方向:

4411aec9ee5e12caea07f73b201d2af1.png

梯度模和方向

梯度角度θ范围从弧度-π到π,然后把它近似到四个方向,分别代表水平,垂直和两个对角线方向(0°,45°,90°,135°)。可以以±iπ/8(i=1,3,5,7)分割,落在每个区域的梯度角给一个特定值,代表四个方向之一。

这里选择Sobel算子计算梯度,相对于其他边缘算子,Sobel算子得出来的边缘粗大明亮。

2d4b17399faf9653eae66b442ae0d926.png

sobel算子

这里选择Sobel算子计算梯度,相对于其他边缘算子,Sobel算子得出来的边缘粗大明亮。

4.非极大值抑制

非极大值抑制是进行边缘检测的一个重要步骤,通俗意义上是指寻找像素点局部最大值。沿着梯度方向,比较它前面和后面的梯度值进行了。

2992153ecff42b5195cf7efd25b06927.png

非极大值抑制

上图中左右图:g1、g2、g3、g4都代表像素点,很明显它们是c的八领域中的4个,左图中c点是我们需要判断的点,蓝色的直线是它的梯度方向,也就是说c要是局部极大值,它的梯度幅值M需要大于直线与g1g2和g2g3的交点,dtmp1和dtmp2处的梯度幅值。但是dtmp1和dtmp2不是整像素,而是亚像素,也就是坐标是浮点的,那怎么求它们的梯度幅值呢?线性插值,例如dtmp1在g1、g2之间,g1、g2的幅值都知道,我们只要知道dtmp1在g1、g2之间的比例,就能得到它的梯度幅值,而比例是可以靠夹角计算出来的,夹角又是梯度的方向。

写个线性插值的公式:设g1的幅值M(g1),g2的幅值M(g2),则dtmp1可以很得到:

M(dtmp1)=wM(g2)+(1-w)M(g1)

其中w=distance(dtmp1,g2)/distance(g1,g2)

distance(g1,g2) 表示两点之间的距离。实际上w是一个比例系数,这个比例系数可以通过梯度方向(幅角的正切和余切)得到。

右边图中的4个直线就是4个不同的情况,情况不同,g1、g2、g3、g4代表c的八领域中的4个坐标会有所差异,但是线性插值的原理都是一致的。

5.双阈值的选取

  • 如果某一像素位置的幅值超过 高 阈值, 该像素被保留为边缘像素。
  • 如果某一像素位置的幅值小于 低 阈值, 该像素被排除。
  • 如果某一像素位置的幅值在两个阈值之间,该像素仅仅在连接到一个高于 高 阈值的像素时被保留。
  • 对于Canny函数的使用,推荐的高低阈值比在2:1到3:1之间。

6、滞后边界跟踪

强边缘点可以认为是真的边缘。弱边缘点则可能是真的边缘,也可能是噪声或颜色变化引起的。为得到精确的结果,后者引起的弱边缘点应该去掉。通常认为真实边缘引起的弱边缘点和强边缘点是连通的,而又噪声引起的弱边缘点则不会。所谓的滞后边界跟踪算法检查一个弱边缘点的8连通领域像素,只要有强边缘点存在,那么这个弱边缘点被认为是真是边缘保留下来。

这个算法搜索所有连通的弱边缘,如果一条连通的弱边缘的任何一个点和强边缘点连通,则保留这条弱边缘,否则抑制这条弱边缘。搜索时可以用广度优先或者深度优先算法。

(二)OpenCV中API函数详解

1、函数原型

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

2、函数功能

Canny函数利用Canny算法来进行图像的边缘检测。

3、参数详解

  • 第一个参数,InputArray类型的image,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位图像;
  • 第二个参数,OutputArray类型的edges,输出的边缘图,需要和源图片有一样的尺寸和类型;
  • 第三个参数,double类型的threshold1,第一个滞后性阈值;
  • 第四个参数,double类型的threshold2,第二个滞后性阈值;
  • 第五个参数,int类型的apertureSize,表示应用Sobel算子的孔径大小,其有默认值3;
  • 第六个参数,bool类型的L2gradient,一个计算图像梯度幅值的标识,有默认值false。

4、实例

#include using namespace cv;int main(){ //载入原始图  Mat src = imread("lena.png"); if (src.empty()) { printf("image error!"); return -1; } Mat src1 = src.clone(); //显示原始图  imshow("【原始图】Canny边缘检测

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

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

相关文章

php登录信息首页显示,首页登录后怎么在首页显示用户名以及隐藏登录框?

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼index.php:登录页面用户名:密码:没有账号?立即注册——————————————————————————doaction.php:header("Content-type:text/html;charsetutf…

python矩阵相乘例题_百道Python入门级练习题(新手友好)第一回合——矩阵乘法...

题目描述【问题描述】编写程序,完成3*4矩阵和4*3整数矩阵的乘法,输出结果矩阵。【输入形式】一行,供24个整数。以先行后列顺序输入第一个矩阵,而后输入第二个矩阵。【输出形式】先行后列顺序输出结果矩阵&a…

笔记本屏幕30hz_你真的了解笔记本电池和电源适配器吗?

很多笔记本硬件配置相似,但续航或性能却相差一大截。实际上,笔记本的续航能力在很大程度上取决于电池;而实际性能,则还会受到电源适配器功率的影响。想认识这两个硬件,就需要从它们的基本参数谈起。笔记本电池笔记本的…

java 俄文,俄文字体在word里面是什么

在Word里输入俄语字母,一打字字体就变成宋体了,俄语字母间间距...我不知道你这个俄语输入法补丁的字库用的是什么,如果是汉字库里好像就没办法调了,试一下把字体改成西文的Times New Roman、Arial等字体看有没有变化,如果没有,那就…

excel公式不自动计算_【纯干货】值得收藏的Excel日期计算公式!

点击上面“零壹快学”关注我们小伙伴们好,今天零壹学长给大家整理了一些常用的日期计算公式,赶紧往下看吧!01根据身份证号计算出生年月--TEXT(MID(A2,7,8),"0-00-00")02根据身份证号提取性别IF(MOD(MID(A2,15,3),2),"男"…

php xml 添加节点 出问题,PHP往XML中添加节点的方法

本文实例讲述了PHP往XML中添加节点的方法。分享给大家供大家参考。具体方法如下:1. contacts.xml代码复制代码 代码如下:JJJManagerNational1971-12-222. php代码复制代码 代码如下:$tel_node null;$doc xmldocfile (contacts.xml);$contact_node $doc->root …

项目开发流程_绿维文旅:旅游项目开发模式与流程

一、旅游项目开发模式旅游综合开发是立足旅游项目自有资源基础,以旅游产业为主导,以市场为导向,以资本为驱动,以资源整合为核心,通过集中土地、资本、技术、交通、劳动力等生产要素,推进土地开发、交通建设…

java创建一个成员方法吗,java构造方法和成员方法的区别

构造方法和成员方法的区别1.构造方法构造方法作用概述给对象的数据进行初始化构造方法格式方法名与类名相同没有返回值类型,连void都没有没有具体的返回值构造方法注意事项如果你不提供构造方法,系统会给出默认构造方法如果你提供了构造方法,…

Java继承_java练习本(20190617)

公众号回复“1”,小刀拉你进学习交流群哟,妈妈再也不担心我学习没人陪伴啦~昨日翻译昨日翻译“The journey of a thousand miles begins with one step.”——Lao Tzu“千里之行始于足下。”——老子今日名言“Imagination was given to man to compensa…

爬虫 页面元素变化_爬虫 基本知识 萌新

爬虫定义网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引…

php 巧用逻辑运算符,php的神奇逻辑运算符

(小乖)今天再读php文档,看到逻辑运算符这边又发现了新天地呀,之前在探究c语言的逻辑运算符中,我们得到了一些结论而在php中,&& ||与and or 同时存在,并且表示的含义是一样,但是不同的是优先级接下来…

gateway sentinel 熔断 不起作用_Sentinel 1.8.0 年度版本发布,熔断降级重构升级

简介:在经过数月的打磨后,Sentinel 1.8.0 版本正式发布!该版本是本年度最重要的版本之一,包含大量特性改进与 bug 修复,尤其是针对熔断降级特性的完善升级(支持任意统计时长、慢调用比例降级策略、熔断器事…

python的getattr和setattr_getattr函数和setattr函数

python内置的两个看起来很简单,一般也不怎么用得上的函数,getattr函数和setattr函数。getattr函数用于获取对象的某个属性的值,setattr函数用于设置对象的某个属性值。getattr函数获取对象的某个属性值,如果属性不存在&#xff0c…

php mongodb排序查询,Mongodb 如何按照内嵌文档的某个字段排序?

现有数据如下{"_id" : ObjectId("5992c90beeb45634df1c2be4"),"name" : "测试数据1","status" : {"product" : [{"id" : ObjectId("59a37f7aef887a1d58b59f4f"),"sort" : 2},{&quo…

access设置0字段为null是因为类型转换失败_Apache Pulsar 2.6.1 版本正式发布:2.6.0 加强版,新增 OAuth2 支持

在 Apache Pulsar 2.6.0 版本发布后的 2 个月,2020 年 8 月 21 日,Apache Pulsar 2.6.1 版本正式发布!Apache Pulsar 2.6.1 修复了 2.6.0 版本中的诸多问题,改进了一些功能,新增了对 OAuth2 的支持,覆盖 Br…

英特尔显卡linux管理_英特尔 11 代酷睿大揭秘:这次全是大招

英特尔在今年九月份正式推出了第 11 代酷睿移动处理器,这次英特尔将 10 纳米 SuperFin 工艺全面带到移动处理器上,同时还有全新的 Willow Cove 内核、Iris Xe 显卡、全新的酷睿及英特尔标志。这次面向消费级市场的英特尔第 11 代酷睿移动处理器又有哪些变…

lnmp php文件访问不了,记一次lnmp环境下无法执行php文件

lnmp环境搭建好后却无法正常执行php文件,坑爹啊!~[错误状况]页面直接打印出php代码内容;php文件无法执行?;查看nginx配置文件:server { listen80;server_name xxxxx.com;access_log/var/log/nginx/xxxxx.ac…

c++矩阵类_面向对象有限元编程|单元类

单元对象是构成整个结构对象的基本要素,如杆单元,梁单元,板单元,壳单元等等。虽然单元形状和特性各不相同,但基本特征和功能是相同的。比如都具有一定的几何形状,通过节点与其它单元连接,包含材…

file 选择的图片作为背景图片_酷炫!用Python把桌面变成实时更新的地球图片

如何拥有够酷炫逼格够高的桌面?本文教你轻松定制自己的桌面背景(建议带上耳机听一下地球的声音)最近疯狂迷恋地球卫星图和地球的卫星视频,看上面的视频简直极度舒适。不禁想把这种图片作为桌面背景图。这就产生抓取其背景图片作为桌面的想法。思路其实很…

摇杆怎么映射到键盘_[评测]YAMAHA PSRSX900:雅马哈升级幅度最大的高端编曲键盘键盘中国原创评测...

本文图片均由本人亲自拍摄,转载请注明出处。年前就收到这台国行PSR-SX900了。在这一个月特殊的日子里,不能出门,幸好有sx900的陪伴,让我可以天天弹琴、唱歌打发时间...现在很多地方开始逐渐复工了,我抽时间写下了这一个…