传统的Canny边缘检测算法是一种有效而又相对简单的算法,可以得到很好的结果(可以参考上一篇Canny边缘检测算法的实现)。但是Canny算法本身也有一些缺陷,可以有改进的地方。

1. Canny边缘检测第一步用高斯模糊来去掉噪声,但是同时也会平滑边缘,使得边缘信息减弱,有可能使得在后面的步骤中漏掉一些需要的边缘,特别是弱边缘和孤立的边缘,可能在双阀值和联通计算中被剔除。很自然地可以预见,如果加大高斯模糊的半径,对噪声的平滑力度加大,但也会使得最后得到的边缘图中的边缘明显减少。这里依然用Lena图为例,保持Canny算法中高阀值100,低阀值50不变,高斯半径分别为2,3,5的Canny边缘二值图像如下。可知高斯模糊把很多有用的边缘信息也模糊掉了,因此如何精确的选择高斯半径就相当重要。

     

高斯半径2                                          高斯半径3                                          高斯半径5

2. 在最初的Canny算法中是使用的最小的2x2领域来计算梯度幅值的。这种方法对噪声很敏感,比较容易检测到伪边缘或漏掉真是边缘。在上一篇算法实现中,实际上使用的是3x3的Sobel梯度算子,是一种比较好的选择。

3. 传统Canny算法的双阀值是全局固定的,因此双阀值大小的选取对最终的结果影响很大,也有一些经验,比如选择低阀值是高阀值的0.4或0.5。然而这毕竟是一种经验选择,阀值的确定仍然很难决定一个最优值。而且一个图像的不同局部区域可能需要各不相同的阀值来精确地找到真实边缘,因此全局阀值就不太合适了。

4. 传统算法仍然可能产生一条宽度大于1的边缘,达不到满意的高精度单点响应。也就是需要继续细化边缘。

下面就一些可以改进的地方做一些讨论。

代替高斯模糊

噪声是高频信号,边缘信号也属于高频信号。既然高斯模糊不加区分的对所有的高频信息进行了模糊,效果自然不尽如人意。那么自然就想到了带有保留边缘功能的各种选择性平滑方法,似乎在这里比高斯模糊会更加合适,那我们就来试一试。带有保留边缘功能的平滑方法的基本思想不是让领域范围内的所有像素都参与该种平滑方法的计算,而是设定一个阀值,仅仅让和中心像素灰度的差值小于这个阀值的像素参与计算。这样和中心像素相差过大的像素被认为是带有有效的信息,而不是噪声,不会参与平滑计算,从而保留了这些有用的高频信号,那么边缘信号自然也在保留的范围。具体的算法可以参考这篇文章http://www.cnblogs.com/Imageshop/p/4694540.html,已经讲得很清楚了。无论是均值平滑,中值平滑,表面模糊,都可以参考这种算法来实现选择性模糊。

应用有保留边缘的选择性模糊来代替高斯模糊后,可以发现,模糊领域的半径值基本影响不了Canny检测的结果,最后的结果只跟选择模糊设定的阀值有关。下面以均值模糊为例,Canny检测的高阀值100低阀值50不变,均值模糊阀值30,不同模糊半径的结果。在均值模糊阀值不变的情况下,不同领域半径下,最后的结果差别不大。

     

均值模糊半径2,阀值30                     均值模糊半径5,阀值30                           均值模糊半径15,阀值30

而保持模糊半径5不变的话,使用不同模糊门限阀值,阀值越大,也就是有越多的领域像素参与模糊计算,最后保留的边缘就越少了。

  

均值模糊半径5,阀值40                         均值模糊半径5,阀值50

相对于高斯模糊,在相同半径下,可以看出应用有保留边缘功能的选择性模糊,明显能保留了更多的边缘细节,使得很多相对较弱的边缘得意保留下来了。我另外还实验了选择性的中值模糊,表面模糊,他们和选择性的均值模糊都能达到类似的效果。这里就不一一列举结果了。其中选择性的表面模糊,因为中心像素的权重高,最后Canny检测结果在参数相同的情况下,保留的边缘相对较多一些。总的来说,应用有保留边缘功能的选择性模糊来代替高斯模糊,参数的选择(领域半径和阀值门限)不像高斯模糊半径参数选择那么严格,所以检测结果更稳定一些。但是参数要多了一个。

梯度算子选择

对于算法中梯度的计算,梯度算子可以有多种选择。我试了一下,如果用一阶梯度算子,Robert交叉算子,他们都是2x2的算子,来代替Sobel,保持高斯模糊半径2,高阀值100低阀值50不变,结果如下。要注意的是,由于一阶梯度算子和Robert算子都是2x2的算子,他们算出来的梯度在幅度上都要小于Sobel算子。即使用同样的高低阀值,最后的结果也不具有可比性。因此,参照Sobel算子的幅度,2x2算子的x,y方向梯度都乘以相应地倍数(4倍),最后进行比较。

     

一阶差分Canny二值图                        Robert交叉梯度Canny二值图                   Sobel算子Canny二值图

可以看到,一阶差分最后的结果在边缘的连通性上是最差的,Robert算子要好一些,Sobel算子最好。在这几种选择当中,似乎Sobel算子是最好的选择。另外还可以使用Prewitt算子和5x5Sobel算子。Prewitt算子也是3x3的,仅仅参数不同,在平滑性能上略微不如Sobel算子。一般来说,比如在Lena图上,Canny边缘结果和用Sobel算子的结果差别不大。5x5Sobel算子在平滑性能上要更强一些。

Canny边缘检测算法的一些改进的更多相关文章

  1. 一些关于Canny边缘检测算法的改进

    传统的Canny边缘检测算法是一种有效而又相对简单的算法,可以得到很好的结果(可以参考上一篇Canny边缘检测算法的实现).但是Canny算法本身也有一些缺陷,可以有改进的地方. 1. Canny边缘 ...

  2. OpenCV: Canny边缘检测算法原理及其VC实现详解(转载)

    原文地址:http://blog.csdn.net/likezhaobin/article/details/6892176 原文地址:http://blog.csdn.net/likezhaobin/ ...

  3. Canny边缘检测算法原理及其VC实现详解(一)

    转自:http://blog.csdn.net/likezhaobin/article/details/6892176 图象的边缘是指图象局部区域亮度变化显著的部分,该区域的灰度剖面一般可以看作是一个 ...

  4. 【算法随记】Canny边缘检测算法实现和优化分析。

    以前的博文大部分都写的非常详细,有很多分析过程,不过写起来确实很累人,一般一篇好的文章要整理个三四天,但是,时间越来越紧张,后续的一些算法可能就以随记的方式,把实现过程的一些比较容易出错和有价值的细节 ...

  5. 十五 Canny边缘检测算法

    一.Canny算法介绍 Canny 的目标是找到一个最优的边缘检测算法,最优边缘检测的含义是: 好的检测- 算法能够尽可能多地标识出图像中的实际边缘. 好的定位- 标识出的边缘要尽可能与实际图像中的实 ...

  6. 【数字图像分析】基于Python实现 Canny Edge Detection(Canny 边缘检测算法)

    Canny 边缘检测算法 Steps: 高斯滤波平滑 计算梯度大小和方向 非极大值抑制 双阈值检测和连接 代码结构: Canny Edge Detection | Gaussian_Smoothing ...

  7. Canny边缘检测算法(基于OpenCV的Java实现)

    目录 Canny边缘检测算法(基于OpenCV的Java实现) 绪论 Canny边缘检测算法的发展历史 Canny边缘检测算法的处理流程 用高斯滤波器平滑图像 彩色RGB图像转换为灰度图像 一维,二维 ...

  8. Canny边缘检测算法原理及其VC实现详解(二)

    转自:http://blog.csdn.net/likezhaobin/article/details/6892629 3.  Canny算法的实现流程 由于本文主要目的在于学习和实现算法,而对于图像 ...

  9. Canny边缘检测算法原理及C语言实现详解

    Canny算子是John Canny在1986年提出的,那年老大爷才28岁,该文章发表在PAMI顶级期刊上的(1986. A computational approach to edge detect ...

随机推荐

  1. Android SDK + Appium 环境搭建

    一.JDK 安装 说明:JDK是包含了JAVA的运行环境(JVM+Java系统类库)和JAVA工具,所以必须最先安装. 链接: https://pan.baidu.com/s/1NfNK_K7vukF ...

  2. Java内存泄漏的几种可能

    Java内存泄漏引起的原因: 内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费称为内存泄漏. 长生命周期的对象持有短生命周期对象的引用就很可能发 ...

  3. Ubuntu 14.03 安装jdk

    安装python-software-properties $sudo apt-get install python-software-properties $sudo apt-get install ...

  4. 更改mysql 和jinkins目录

    更改MySQL数据目录 1.修改my.cnf,注销原datadir,增加新的数据目录 #datadir=/var/lib/mysqldatadir=/mysql-data/mysql 2.修改启动脚本 ...

  5. 一次sendmsg的改造过程

    比较蛋疼的一个改造过程,简单记录一下. 场景:用户态使用sendmsg发包,tcp报文,由于内核实现过程中存在一次kernel_read,也就是存在将pagecache中的内容拷贝一次的问题. 为了减 ...

  6. [Shell]Bash变量:数值运算及运算符

    ------------------------------------------------------------------------------------------------- Sh ...

  7. Pandas合并数据集之concat、combine_first方法

    轴向连接(concat) Numpy import numpy as np import pandas as pd from pandas import Series arr = np.arange( ...

  8. jQuery截取字符串的几种方法

    1.取后缀 var fileDir = $("#file").val(); var suffix = fileDir.substr(fileDir.lastIndexOf(&quo ...

  9. python狂犬病大数据分析

    一.被动物咬伤.抓伤者,年龄以45-59岁年龄组为最多(占30.66%). 45-59岁年龄段的人与动物接触较多.被侵害的机会最多.其次受伤机会较多的是15-44岁年龄阶段的人,而7岁及以下儿童受伤比 ...

  10. m文件转换c代码

    parametet.mclc; clear; load('src.mat') CZT_N = ; CZT_M = ; CZT_W = exp(-j*(*pi/)); CZT_A = exp(j**pi ...