Canny边缘检测算法的基础是图像梯度,Canny边缘检测算法是一种使用多步骤算法对图像中大范围边缘进行识别探测的方法。Canny算法在1986年由John F Canny提出,是一种从不同视觉物体提取有用的结构信息并可以显著地减少数据处理量的边缘检测技术,目前已经应用在不同的计算机视觉系统中。Canny还发现不同的视觉系统对边缘检测的需求是近似的。因此,一种能满足诸多需求的边缘提取解决方案可以在大范围场景中使用。一般的边缘提取指标要求包含以下几个方面:

  1. 边缘检测的识别率要高,边缘检测算法可以精确识别到图像中尽可能多的图片边缘信息;
  2. 算法要能定位到边缘的中心;
  3. 图像中的噪声不能造成边缘检测的误识别现象,并且已经被识别到的边缘只应该被检测一次。

为了满足这些需求,Canny使用变分算法进行研究,变分算法技术就是找到优化函数的最佳指标。在Canny算法中,优化函数通过四个指数项和进行描述,被近似为一阶高斯导数。

在已有的众多边缘探测算法中,Canny是最可靠和严密的。由于符合上述三条指标原则且易于实现,其已成为边缘检测领域最为流行的算法之一。Canny的实现流程可以分为以下五个部分:

  1. 通过高斯滤波对图像进行平滑;
  2. 计算图像的灰度梯度;
  3. 使用梯度幅度阈值分割和下限截止抑制方法避免边缘探测的虚假识别现象出现;
  4. 使用双边阈值确定潜在的边缘;
  5. 通过滞回现象追踪边缘,具体方法为:通过对弱小和没有与强边缘连接的边缘进行抑制,进而完成边缘探测。

由于所有的边缘检测结果都会受图像中的噪声影响,滤除产生次影响的噪声是十分必要的。一个高斯滤波器与图像进行卷积运算实现了图像平滑,此步骤通过对图像进行轻微平滑的方式减弱噪声对边缘探测的影响。大小为(2k+1)✖️(2k+1)的高斯滤波器核的方程表达式为:

python深度学习边缘检测 canny边缘检测算法python_边缘检测

其中python深度学习边缘检测 canny边缘检测算法python_算法_02代表高斯滤波器核中第python深度学习边缘检测 canny边缘检测算法python_算法_03python深度学习边缘检测 canny边缘检测算法python_opencv_04列个元素的值。下式是利用该公式生成的一个5✖️5卷积核,其中python深度学习边缘检测 canny边缘检测算法python_python深度学习边缘检测_05

python深度学习边缘检测 canny边缘检测算法python_python深度学习边缘检测_06

原彩色图片为:

python深度学习边缘检测 canny边缘检测算法python_python_07


将上述图像变换为灰度图后用上述高斯核平滑滤波之后的效果为:

python深度学习边缘检测 canny边缘检测算法python_opencv_08


高斯核维度的选择会影响边缘检测的性能,理解这一点是很重要的。高斯核维度越大,检测器对噪声的敏感性越低。另外,边缘探测过程中定位误差会随着高斯核维度的增加轻微增加。一个5×5大小的高斯核对大多数情况而言是比较好的,但这也不绝对,视具体情况而异,在某些特殊场景会稍有特殊情况。下面寻找图像各个像素的灰度梯度值。

由于图像中的边缘可能指向任何方向,因此Canny算法使用四个滤波器去探测模糊后的图像中的水平、垂直和对角线边缘。诸如Roberts、Prewitt、Sobel等边缘检测算子会分别返回沿水平/垂直方向的一阶差分值python深度学习边缘检测 canny边缘检测算法python_边缘检测_09python深度学习边缘检测 canny边缘检测算法python_opencv_10,通过python深度学习边缘检测 canny边缘检测算法python_边缘检测_09python深度学习边缘检测 canny边缘检测算法python_opencv_10可以得到如下计算结果:

python深度学习边缘检测 canny边缘检测算法python_opencv_13
python深度学习边缘检测 canny边缘检测算法python_python深度学习边缘检测_14可以通过取模运算获取,而python深度学习边缘检测 canny边缘检测算法python_边缘检测_15可以通过反正切函数计算获取。边缘角度计算结果被整合分成四种类型,分别代表垂直、水平和两个对角线方向(0°、45°、90°和135°)。在上述四个方向附近的值会被自动赋值为最接近的方向角度,如[0°,22.5°]或[157.5°,180°]之间的角度被自动复制为0°。

最小梯度截止抑制或者下限截止抑制是边缘细化技术。下限截止抑制技术是为了找到灰度尖锋变换最大的位置,针对梯度图中每个像素的具体算法为:

  1. 比较当前像素和正/反方向的边缘强度;
  2. 如果当前像素的边缘强度是当前位置梯度方向的中最大的,则该位置的值被保留,否则被放弃;

在一些实现过程中,算法将连续的梯度方向分类成一小组离散的方向,然后将一个3✖️3的滤波器沿着之前输出的步数移动(步数是边缘强度和梯度方向)。在每个像素上,当梯度量级不大于梯度方向上的两个梯度邻域时,中心像素的边缘强度将被抑制。例如:如果圆梯度角度为0° (梯度边缘在南-北方向),如果梯度量级大于在东-西方向的梯度量级,这个点将被视作在边缘上;如果圆梯度角度为90°(边缘沿东-西方向),如果该点的梯度量级高于在南北方向上的其他点,该点将被视作在边缘上;当圆梯度角度为45°和135°时,以此类推。这个问题的图形化表达如下图所示:

python深度学习边缘检测 canny边缘检测算法python_算法_16

在跟精确的应用项目中,线性插值被用于两个横跨梯度方向的两个邻域像素中。例如,如果梯度角在89°和180°之间,在北向和东北向梯度之间的插值函数将提供一个插值结果,在南向和西南向像素之间的插值将提供另一个。中心像素的梯度量级必须要大于这两个,因为这个中心像素被标记为了一个边缘点。

非极大值抑制:

在得到了梯度大小和方向之后,将对整个图片进行一次全面扫描,目的是移除不构成边缘的像素。为实现此功能,每个像素都会被确认自己是不是沿着梯度方向上邻域内梯度值最大的那个一个,如下图所示:

python深度学习边缘检测 canny边缘检测算法python_python_17


如上图所示,A点在垂直方向是处于边缘上,梯度方向是边缘的法向方向。B点和C点均在梯度方向上,因此A点就和B、C点比较一下自己的梯度是否是局部最大值。如果是,A点就被应用到下一阶段,否则其被抑制为0。简而言之,按照上述理论计算的二值图像中的结果是细边缘,也可以用下图表达:

python深度学习边缘检测 canny边缘检测算法python_opencv_18

主要是看这个点的梯度是不是周围具有相同梯度方向的点中最大的。

双阈值:
在非最大抑制应用后,剩余的边缘像素为图像中的真实边缘提供了一个更加精确的表达方式。但是,一些边缘的剩余是由于噪声和颜色变化造成的。为了对这些虚假响应做出解释,有必要用一个弱梯度值将边缘像素滤除并永一个高梯度值保留边缘像素。这个工作通过选择高低阈值来实现,如下图所示。

python深度学习边缘检测 canny边缘检测算法python_算法_19

如果一个边缘像素的梯度值高于高阈值,它就被标记为强边缘像素。反之如果小于高阈值且大于低阈值,它就被标记为弱边缘像素。如果边缘像素梯度值小于低阈值,它将被取消。两个阈值是从经验上确定的同时他们的定义将依赖于给定输入图像的内容。

通过滞回现象跟踪边缘:

至此,强边缘像素应该被明确的包含在边缘图像中了。但是弱边缘可以代表真实的边缘图像,也可以在噪声或者颜色变化。为了实现精确处理,由于噪声或颜色变化引起的弱边缘应该被直接剔除。通常一个由真实边缘引起的弱边缘像素应该被一个强边缘像素连接,而由于噪声/颜色变化引起的弱边缘与强边缘像素是不连接的。为了跟踪边缘的连接性,通过观测弱边缘像素和它的8联通域像素进行BLOB分析。只要在BLOB区域内有一个强边缘,弱边缘便被标识为应该被保留。

python深度学习边缘检测 canny边缘检测算法python_算法_20


总之,实现Canny边缘检测需要五步,对算法进行演练,首先载入一张高清原图片:

python深度学习边缘检测 canny边缘检测算法python_算法_21


对图像灰度化并用5×5的高斯核滤波器对其进行平滑,其中σ=1.4,结果如下图所示:

python深度学习边缘检测 canny边缘检测算法python_算法_22


生成灰度图的灰度梯度图像,图像边缘已通过复制方式处理,灰度梯度图像如下图所示:

python深度学习边缘检测 canny边缘检测算法python_python深度学习边缘检测_23

对上图进行非极大值抑制,效果如下图所示:

python深度学习边缘检测 canny边缘检测算法python_算法_24


对上图进行双边阈值操作。将梯度值在0.1至0.3之间的视为弱像素,而高于0.3的是强像素,处理后效果如下图所示:

python深度学习边缘检测 canny边缘检测算法python_opencv_25


最后进行滞回操作,效果如下图所示:

python深度学习边缘检测 canny边缘检测算法python_算法_26

在python中通过cv2.Canny()函数实现这个功能,函数参数如下图所示:

python深度学习边缘检测 canny边缘检测算法python_算法_27