图象的边缘是指图象局部区域亮度变化显著的部分,该区域的灰度剖面一般能够看作是一个阶跃,既从一个灰度值在非常小的缓冲区域内急剧变化到还有一个灰度相差较大的灰度值。图象的边缘部分集中了图象的大部分信息,图象边缘的确定与提取对于整个图象场景的识别与理解是非常重要的,同一时候也是图象切割所依赖的重要特征,边缘检測主要是图象的灰度变化的度量、检測和定位,自从1959提出边缘检測以来,经过五十多年的发展,已有很多中不同的边缘检測方法。依据作者的理解和实践,本文对边缘检測的原理进行了描写叙述,在此基础上着重对Canny检測算法的实现进行详述。

本文所述内容均由编程验证而来,在实现过程中,有不论什么错误或者不足之处大家共同讨论(本文不讲述枯燥的理论证明和数学推导,只从算法的实现以及改进上进行原理性和project化的描写叙述)。

1、边缘检測原理及步骤

在之前的博文中,作者从一维函数的跃变检測開始,循序渐进的对二维图像边缘检測的基本原理进行了通俗化的描写叙述。结论是:实现图像的边缘检測,就是要用离散化梯度逼近函数依据二维灰度矩阵梯度向量来寻找图像灰度矩阵的灰度跃变位置,然后在图像中将这些位置的点连起来就构成了所谓的图像边缘(图像边缘在这里是一个统称,包含了二维图像上的边缘、角点、纹理等基元图)。

在实际情况中理想的灰度阶跃及其线条边缘图像是非常少见到的,同一时候大多数的传感器件具有低频滤波特性,这样会使得阶跃边缘变为斜坡性边缘,看起来当中的强度变化不是瞬间的,而是跨越了一定的距离。这就使得在边缘检測中首先要进行的工作是滤波。

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

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

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

2、Canny边缘检測算法原理

JohnCanny于1986年提出Canny算子,它与Marr(LoG)边缘检測方法类似,也属于是先平滑后求导数的方法。本节对依据上述的边缘检測过程对Canny检測算法的原理进行介绍。

2.1 对原始图像进行灰度化

Canny算法通常处理的图像为灰度图,因此假设摄像机获取的是彩色图像,那首先就得进行灰度化。对一幅彩色图进行灰度化,就是依据图像各个通道的採样值进行加权平均。以RGB格式的彩图为例,通常灰度化採用的方法主要有:

方法1:Gray=(R+G+B)/3;

方法2:Gray=0.299R+0.587G+0.114B;(这样的參数考虑到了人眼的生理特点)

注意1:至于其它格式的彩色图像,能够依据对应的转换关系转为RGB然后再进行灰度化;

注意2:在编程时要注意图像格式中RGB的顺序通常为BGR

2.2 对图像进行高斯滤波

图像高斯滤波的实现能够用两个一维高斯核分别两次加权实现,也能够通过一个二维高斯核一次卷积实现。

1)高斯核实现

上式为离散化的一维高斯函数,确定參数就能够得到一维核向量。

上式为离散化的二维高斯函数,确定參数就能够得到二维核向量。

注意1:关于參数Sigma的取值详见上篇博文。

注意2:在求的高斯核后,要对整个核进行归一化处理。

2)图像高斯滤波

对图像进行高斯滤波,听起来非常玄乎,事实上就是依据待滤波的像素点及其邻域点的灰度值依照一定的參数规则进行加权平均。这样能够有效滤去理想图像中叠加的高频噪声。

通常滤波和边缘检測是矛盾的概念,抑制了噪声会使得图像边缘模糊,这回添加边缘定位的不确定性;而假设要提高边缘检測的灵敏度,同一时候对噪声也提高了灵敏度。实际project经验表明,高斯函数确定的核能够在抗噪声干扰和边缘检測精确定位之间提供较好的折衷方案。这就是所谓的高斯图像滤波,详细实现代码见下文。

2.3 用一阶偏导的有限差分来计算梯度的幅值和方向

关于图像灰度值得梯度可使用一阶有限差分来进行近似,这样就能够得图像在x和y方向上偏导数的两个矩阵。经常使用的梯度算子有例如以下几种:

1)Roberts算子

上式为其x和y方向偏导数计算模板,可用数学公式表达其每一个点的梯度幅值为:

2)Sobel算子

上式三个矩阵分别为该算子的x向卷积模板、y向卷积模板以及待处理点的邻域点标记矩阵,据此可用数学公式表达其每一个点的梯度幅值为:

3)Prewitt算子

和Sobel算子原理一样,在此仅给出其卷积模板。

4)Canny算法所採用的方法

在本文实现的Canny算法中所採用的卷积算子比較简单,表达例如以下:

其x向、y向的一阶偏导数矩阵,梯度幅值以及梯度方向的数学表达式为:

求出这几个矩阵后,就能够进行下一步的检測过程。

2.4 对梯度幅值进行非极大值抑制

图像梯度幅值矩阵中的元素值越大,说明图像中该点的梯度值越大,但这不不能说明该点就是边缘(这不过属于图像增强的过程)。在Canny算法中,非极大值抑制是进行边缘检測的重要步骤,通俗意义上是指寻找像素点局部最大值,将非极大值点所相应的灰度值置为0,这样能够剔除掉一大部分非边缘的点(这是本人的理解)。

图1 非极大值抑制原理

依据图1 可知,要进行非极大值抑制,就首先要确定像素点C的灰度值在其8值邻域内是否为最大。图1中蓝色的线条方向为C点的梯度方向,这样就能够确定其局部的最大值肯定分布在这条线上,也即出了C点外,梯度方向的交点dTmp1和dTmp2这两个点的值也可能会是局部最大值。因此,推断C点灰度与这两个点灰度大小就可以推断C点是否为其邻域内的局部最大灰度点。假设经过推断,C点灰度值小于这两个点中的任一个,那就说明C点不是局部极大值,那么则能够排除C点为边缘。这就是非极大值抑制的工作原理。

作者觉得,在理解的过程中须要注意下面两点:

1)中非最大抑制是回答这样一个问题:“当前的梯度值在梯度方向上是一个局部最大值吗?”
所以,要把当前位置的梯度值与梯度方向上两側的梯度值进行比較;

2)梯度方向垂直于边缘方向。

但实际上,我们仅仅能得到C点邻域的8个点的值,而dTmp1和dTmp2并不在当中,要得到这两个值就须要对该两个点两端的已知灰度进行线性插值,也即依据图1中的g1和g2对dTmp1进行插值,依据g3和g4对dTmp2进行插值,这要用到其梯度方向,这是上文Canny算法中要求解梯度方向矩阵Thita的原因。

完毕非极大值抑制后,会得到一个二值图像,非边缘的点灰度值均为0,可能为边缘的局部灰度极大值点可设置其灰度为128。依据下文的详细測试图像能够看出,这样一个检測结果还是包括了非常多由噪声及其它原因造成的假边缘。因此还须要进一步的处理。

2.5 用双阈值算法检測和连接边缘

Canny算法中降低假边缘数量的方法是採用双阈值法。选择两个阈值(关于阈值的选取方法在扩展中进行讨论),依据高阈值得到一个边缘图像,这样一个图像含有非常少的假边缘,可是因为阈值较高,产生的图像边缘可能不闭合,未解决这样一个问题採用了另外一个低阈值。

在高阈值图像中把边缘链接成轮廓,当到达轮廓的端点时,该算法会在断点的8邻域点中寻找满足低阈值的点,再依据此点收集新的边缘,直到整个图像边缘闭合。

以上即为整个Canny边缘检測算法的原理分析,接下来我们进行VC下的算法实现和效果分析。

Canny边缘检測算法原理及其VC实现具体解释(一)的更多相关文章

  1. 图像处理之Canny边缘检測

    图像处理之Canny 边缘检測 一:历史 Canny边缘检測算法是1986年有John F. Canny开发出来一种基于图像梯度计算的边缘 检測算法,同一时候Canny本人对计算图像边缘提取学科的发展 ...

  2. OpenCV2马拉松第17圈——边缘检測(Canny边缘检測)

    计算机视觉讨论群162501053 转载请注明:http://blog.csdn.net/abcd1992719g 收入囊中 利用OpenCV Canny函数进行边缘检測 掌握Canny算法基本理论 ...

  3. 图像边缘检測--OpenCV之cvCanny函数

    图像边缘检測--OpenCV之cvCanny函数 分类: C/C++ void cvCanny( const CvArr* image, CvArr* edges, double threshold1 ...

  4. 【OpenCV新手教程之十二】OpenCV边缘检測:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/25560901 作者:毛星云(浅墨) ...

  5. Python下opencv使用笔记(七)(图像梯度与边缘检測)

    梯度简单来说就是求导,在图像上表现出来的就是提取图像的边缘(无论是横向的.纵向的.斜方向的等等),所须要的无非也是一个核模板.模板的不同结果也不同.所以能够看到,全部的这些个算子函数,归结究竟都能够用 ...

  6. Python图像处理(8):边缘检測

    快乐虾 http://blog.csdn.net/lights_joy/ 欢迎转载,但请保留作者信息 此前已经得到了单个区域植株图像,接下来似乎应该尝试对这些区域进行分类识别.通过外形和叶脉进行植物种 ...

  7. OpenCV图像处理篇之边缘检測算子

    3种边缘检測算子 灰度或结构等信息的突变位置是图像的边缘,图像的边缘有幅度和方向属性.沿边缘方向像素变化缓慢,垂直边缘方向像素变化剧烈.因此,边缘上的变化能通过梯度计算出来. 一阶导数的梯度算子 对于 ...

  8. OpenCV2马拉松第15圈——边缘检測(Laplace算子,LOG算子)

    收入囊中 拉普拉斯算子 LOG算子(高斯拉普拉斯算子) OpenCV Laplacian函数 构建自己的拉普拉斯算子 利用拉普拉斯算子进行图像的锐化 葵花宝典 在OpenCV2马拉松第14圈--边缘检 ...

  9. Cocos2d-x教程(34)-三维物体OBB碰撞检測算法

    欢迎增加Cocos2d-x 交流群:193411763 个中心点.1个旋转矩阵和3个1/2边长(注:一个旋转矩阵包括了三个旋转轴,若是二维的OBB包围盒则是一个中心点,两个旋转轴,两个1/2边长). ...

随机推荐

  1. ios常见加密解密方法

    在其他平台中经常会计算MD5值,在iOS平台中也提供了该方法,首先需要导入头文件 #import <CommonCrypto/CommonDigest.h> 方法CC_MD5可以获取MD5 ...

  2. levelDB跳表实现

    跳表的原理就是利用随机性建立索引,加速搜索,并且简化代码实现难度.具体的跳表原理不再赘述,主要是看了levelDB有一些实现细节的东西,凸显自己写的实现不足之处. 去除冗余的key template& ...

  3. Pyton——int内部功能介绍

    int内部功能详解: class int(object): """ int(x=0) -> integer int(x, base=10) -> intege ...

  4. ASP.NET MVC 5 学习教程:通过控制器访问模型的数据

    原文 ASP.NET MVC 5 学习教程:通过控制器访问模型的数据 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连 ...

  5. perl 安装 ZooKeeper模块

    1072 ./configure --libdir=/usr/lib 1073 make 1074 make install 1075 cpan ZooKeeper [root@wx03 c]# pe ...

  6. Win8.1应用开发之异步编程

    在win8应用商店开发时,我们会遇到很多异步方法.它们存在的目的就是为了确保你的应用在运行须要大量时间的任务时仍能保持良好的响应,也就是说调用异步API是为了响应用户的操作.设想一下我们点击一个But ...

  7. ZOJ 3594 年份水题 【注意:没有0年】

    #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #i ...

  8. 使用VirtualBox SDK之初步编译

    VirtualBox成功编译出来后,在生成的out文件夹中会发现有SDK文件夹(当然也可以直接从官网下SDK),里面有例子,但是直接用Visual Studio编译的话会出一大堆错误,本文就是讲解如何 ...

  9. Mac中QT程序发布

    基于Qt开发的应用程序进驻Mac App Store 最近摸索着将一个基于用Qt开发的App发布到Mac App Store,在网上查找相关资料的时候,发现很多文档都过期了,要有一些修改,所以想记录下 ...

  10. json datetime转换问题

    我用Newtonsoft.Json.dll转换成json,这次是把一个集合转换成json,这个集合里有个DateTime类型的数据,转换完成后会变成/Date(1286375605000+0800)/ ...