传统的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. Bootstrap关闭当前页

       function doBack() {        var index = parent.layer.getFrameIndex(window.name);        parent.lay ...

  2. Oracle 学习笔记(五)

    --表空间,auto: 自动管理, manual: 手动管理   create tablespace  tsp1 datafile 'D:\ORACLE\ORADATA\O10\tsp1.dbf'   ...

  3. Python学习笔记---切片 列表 元祖 字典 集合

    列表[1,2,3,2]#[] 元祖(1,2,3,2)#() 字典{1:2,3:2}#{} 集合{1,2,3,2}#{} 1,集合与列表的区别,集合里不能有重复元素 2.字典与集合的区别,都是用花括号表 ...

  4. maven项目发布到tomcat的错误

    Could not publish to the server. java.lang.IndexOutOfBoundsException "Updating status for Tomca ...

  5. oracle sql developer怎么创建用户

    学习数据库的时候,用管理员账户,会有会有很多系统自创的表,很麻烦.所以要自己创建普通用户. create user 用户名 identified by 密码;--创建用户 grant connect, ...

  6. Pandas数据的去重,替换和离散化,异常值的检测

    数据转换 移除重复数据 import pandas as pd import numpy as np from pandas import Series data = pd.DataFrame( {' ...

  7. Linux云服务器

    1. 第一步:前往阿里云官网注册账号,实名认证.进去云服务器,创建实例! 第二步:选配置,**公网IP地址选择“分配”!**如果你是首次购买主机,安全组先不必勾选,或者勾选默认的 .后面,会有安全组的 ...

  8. Springboot学习06-Spring AOP封装接口自定义校验

    Springboot学习06-Spring AOP封装接口自定义校验 关键字 BindingResult.Spring AOP.自定义注解.自定义异常处理.ConstraintValidator 前言 ...

  9. sqlserver2017 重装过程中出现“无法找到数据库引擎启动句柄”错误的解决办法

    sqlserver数据库引擎修改账号名,详情参考:http://blog.51cto.com/djclouds/2089047?utm_source=oschina-app 在SQL Server安装 ...

  10. [leetcode]30. Substring with Concatenation of All Words由所有单词连成的子串

    You are given a string, s, and a list of words, words, that are all of the same length. Find all sta ...