传统的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. Redis管理:安全/耗时命令日志与命令监控/数据库管理工具

    1.安全管理 1)绑定指定IP Redis的安全设计是在“Redis运行在可信环境”这个前提之下的,在生产环境中建议通过应用程序连接Redis.Redis可以配置只接受来自指定IP的的请求,可通过修改 ...

  2. Python全栈开发记录_第二篇(文件操作及三级菜单栏增删改查)

    python3文件读写操作(本篇代码大约100行) f = open(xxx.txt, "r", encoding="utf-8") 不写“r”(只读)默认是只 ...

  3. spring cloud 学习目录

    1.spring cloud简单示例 2.spring cloud快速入门 3.spring cloud 常用 4.spring cloud 原理 5.spring cloud 源码分析 6.spri ...

  4. JVM内存区域详解(Eden Space、Survivor Space、Old Gen、Code Cache和Perm Gen)

    JVM区域总体分两类,heap区和非heap区.heap区又分为: Eden Space(伊甸园). Survivor Space(幸存者区). Old Gen(老年代). 非heap区又分: Cod ...

  5. Java 学习 UUID 与 时间格式化、时间操作

    UUID : UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,是一种软件建构的标准,亦为开放软件基金会组织在分布式计算环境领域的一部分.其目的,是让分 ...

  6. scp: command not found

    scp 不能用? [root@doc]# scp jdk-8u144-linux-x64.tar.gz root@10.10.10.17:/root/ root@10.10.10.17's passw ...

  7. python练习题_01

    1.执行python的两种方式 答:1.通过解释器执行1.py 2.通过cmd执行python,再执行1.py 2.简述位与字节的的关系 答:8位=1字节(计算机处理时以字节为单位,存储时以位为单位) ...

  8. 触发full gc的条件

    1.调用System.gc 2.老年代空间不足 3.永生区空间不足 4.CMS GC时出现promotion failed和concurrent mode failure 5.统计得到的Minor G ...

  9. SQL Server与MySQL在“存在则更新,不存在则插入”并发处理上的一些差异。

    “存在则更新,不存在则插入的逻辑”并发情况下的处理 在sqlserver中: 在sqlserver中,是通过可序列化隔离级别+排它锁的方式来锁定一个范围来实现的当前锁定一个不存在的记录的时候,sqls ...

  10. apt与apt-get命令的区别与解释

    [apt与apt-get命令的区别与解释] Ubuntu 16.04 发布时,一个引人注目的新特性便是 apt 命令的引入.其实早在 2014 年,apt 命令就已经发布了第一个稳定版,只是直到 20 ...