边缘检测(1):概述

561 阅读5分钟

本篇是边缘检测系列的第一篇,将大致介绍边缘检测的目的以及一些基础知识。

本文部分素材来源于Stanford大学的CS131课程。

边缘检测的目的

边缘检测顾名思义就是检测图像中的物体边缘,对于计算机来说,通过对边缘的检测可以提取相关的信息,从而进行对物体的识别。

本质上来说,边缘检测就是检测图片上的不连续成分,这些不连续包括:物品表面普通的不连续、深度的不连续、表面颜色的不连续以及光照强度的不连续等。

image.png

图像的梯度

既然边缘检测的重点是图片上的不连续成分,那很显然梯度是判断连续性的主要工具(这里连续与数学意义上的连续不是同一概念,在数学上不连续函数是不可导的)。 梯度的本意是一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模)。 对图像求梯度,即意味着需要在二维空间中求离散梯度。

二元梯度

假设有二元函数f(x,y)f(x,y),则有其梯度向量:

f(x,y)=[δf(x,y)δxδf(x,y)δy]=[fxfy]\nabla f(x,y)= \left[ \begin{matrix} \frac{\delta f(x,y)}{\delta x}\\ \frac{\delta f(x,y)}{\delta y} \end{matrix} \right]= \left[ \begin{matrix} f_x\\ f_y \end{matrix} \right]

梯度值:

f(x,y)=fx2+fy2|\nabla f(x,y)|=\sqrt{f_x^2+f_y^2}

梯度方向:

θ=tan1(δfδy/δfδx)\theta = tan^{-1}\left(\frac{\delta f}{\delta y} / \frac{\delta f}{\delta x}\right)

二元离散梯度滤波器

若要对一个图像(即二维矩阵)求梯度,其横向滤波器为:

13[101101101]\frac{1}{3} \left[ \begin{matrix} 1&0&-1\\ 1&0&-1\\ 1&0&-1 \end{matrix} \right]

纵向滤波器为:

13[111000111]\frac{1}{3} \left[ \begin{matrix} 1&1&1\\ 0&0&0\\ -1&-1&-1 \end{matrix} \right]

比如对于矩阵:

I=[10102020201010202020101020202010102020201010202020]I= \left[ \begin{matrix} 10&10&20&20&20\\ 10&10&20&20&20\\ 10&10&20&20&20\\ 10&10&20&20&20\\ 10&10&20&20&20 \end{matrix} \right]

将上述横向滤波器作用于II,得到:

Ix=[0000001010000101000010100000000]I_x= \left[ \begin{matrix} 0&0&0&0&0\\ 0&10&10&0&0\\ 0&10&10&0&0\\ 0&10&10&0&0\\ 0&0&0&0&0 \end{matrix} \right]

下图为将一张图片横向纵向分别求导的结果:

简单的边缘检测器

边缘的特征

最简单的边缘检测器就是检测图像上强度变化剧烈的地方。 比如对于下面左侧图中红线一行的强度变化如右上图所示,可以明显观察到,有边缘的地方,强度变化十分剧烈。 二如果对强度函数求离散梯度,即可得到右下图,梯度值较大的地方即为强度函数变化剧烈的地方,也就是图像上边缘所在地方。

利用上一节中我们已经得到的梯度向量公式、梯度值公式和梯度方向公式即可求出图像上每一点的梯度。

噪声的影响与解决方法

上一小节中我们得到了边缘的特征——即图像强度的梯度值较大的地方,但实际情况并不如此美好。 图像上经常会有很多噪声,这些在这些噪声所在的地方我们的梯度值往往会变得很大,依照我们对边缘特征的定义,就会把这些噪声也视作边缘,导致我们找不到真正的边缘所在:

图片名称

对于这种噪声,我们的解决方案是对图像进行平滑处理,使得那些和相邻的像素均显著不同的像素“看起来”更像周围的像素。

具体对图像进行平滑的方式,一般采用高斯平滑,其在二维空间的定义为:

G(u,v)=12πσ2e(u2+v2)/2σ2G(u,v)=\frac{1}{2\pi \sigma^2}e^{-(u^2+v^2)/2\sigma^2}

其中uuvv是两个方向的模糊范围,σ\sigma为标准差。 在离散空间中,分布不为零的像素组成的卷积矩阵与原始图像做变换。每个像素的值都是周围相邻像素值的加权平均。原始像素的值有最大的高斯分布值,所以有最大的权重,相邻像素随着距离原始像素越来越远,其权重也越来越小。这样进行模糊处理比其它的均衡模糊滤波器更高地保留了边缘效果。关于从连续高斯函数到离散空间形式的变换,可参考维基百科上尺度空间变换这一篇。

使用numpy产生高斯核的代码如下:

def gaussian_kernel(size, sigma):
    kernel = np.zeros((size, size))
    k = int((size - 1) / 2)
    parameter = 1 / (2 * np.pi * sigma ** 2)
    for i in range(2 * k + 1):
        for j in range(2 * k + 1):
            kernel[i][j] = parameter * np.exp(-((i - k) ** 2 + (j - k) ** 2) / (2 * sigma ** 2))

    return kernel

比如产生大小为3×33\times 3,标准差为1的高斯核,结果为:

经过高斯平滑后,上图中带噪声的函数即可得到“干净”的梯度函数:

在高斯函数参数的选择上,要注意平滑度与局部化之间的平衡,如果平滑程度过高,会将原有的边缘模糊掉,导致我们的目标发生偏离。

什么是好的边缘检测器

设计一个好的边缘检测器,有以下三个原则:

  • 检测准确度高:一个好的边缘检测器必须尽可能降低假阳性(即由于噪声导致检测到原本不存在的边缘)和假阴性(真正的边缘没有被检测到)
  • 局部化程度高:检测出的边缘必须与真实边缘尽可能贴近
  • 单一响应:检测器对于一个真实边缘只能检测出一条边,即最小化真实边缘附近的局部最大值

本文小结

本文简单介绍了边缘检测的目标以及一些基础知识,下一篇文章将介绍几个经典的边缘检测器。