点击上方
“
小白学视觉
”,选择加"
星标
"或“
置顶
”
重磅干货,第一时间送达
作者:姚童,Datawhale优秀学习者,华北电力大学
严格的说,梯度计算需要求导数。但是图像梯度的计算,是通过计算像素值的差得到梯度的近似值。图像梯度表示的是图像变化的速度,反映了图像的边缘信息。
边缘是像素值快速变化的地方。所以对于图像的边缘部分,其灰度值变化较大,梯度值也较大;对于图像中较平滑的部分,其灰度值变化较小,梯度值也较小。
为了检测边缘,我们需要检测图像中的不连续性,可以使用图像梯度来检测不连续性。
但是,图像梯度也会受到噪声的影响,因此建议先对图像进行平滑处理。
1. 图像梯度与几种算子
Sobel算子
Scharr算子
Roberts算子
Laplacian算子
2. Canny边缘检测
高斯滤波
计算梯度强度和方向
非极大值抑制(NMS)
用双阈值算法检测和连接边缘
3. 基于OpenCV的实现
Sobel算子函数
Scharr算子
Laplacian算子
一、
图像梯度与几种算子
“滤波器”也可以称为“卷积核”,“掩膜”,“算子”等。
1.1 Sobel算子
Sobel算子是一个3×3的卷积核,利用局部差分寻找边缘,计算得到梯度的近似值。x和y方向的Sobel算子分别为:
梯度有方向,对于一个图像,可以通过Sobel算子分别计算水平方向和垂直方向的偏导数的近似值。
计算水平方向偏导数的近似值
设原图像大小为
,水平方向偏导数
为:
计算像素点P5的梯度,需要利用邻域内的像素点,公式为:
即用像素点P5右侧像素值减去左侧像素值,距离P5近的点权重较大,为2;距离P5远的点权重较小,为1。
计算垂直方向偏导数的近似值
设原图像大小为
,垂直方向偏导数
为:
计算像素点P5的梯度,需要利用邻域内的像素点,公式为:
即用像素点P5下一行的像素值减去上一行的像素值,距离P5近的点权重较大,为2;距离P5远的点权重较小,为1。
1.2 Scharr算子
x和y方向的Scharr算子分别为:
Sobel算子与Scharr算子比较:Sobel算子的缺点是,当结构较小是,精确度不高,Scharr算子具有更高的精度。
1.3 Roberts算子
当图像边缘接近于正45°或负45°时,该算法处理效果更理想。其缺点是对边缘的定位不太准确,提取的边缘线条较粗。正45°和负45°方向的Roberts算子分别为:
Laplacian算子是一种二阶导数算子,具有旋转不变性,可以满足不同方向的边缘检测要求。通常其算子的系数之和需要为0。
计算P5的近似导数值,如下:
Canny边缘检测是一种多级边缘检测算法。于1986年由John F. Canny在论文《A Computational Approach to Edge Detection》中提出。
Canny边缘检测是从不同视觉对象中提取有用的结构信息并大大减少要处理的数据量的一种技术,目前已广泛应用于各种计算机视觉系统。Canny发现,在不同视觉系统上对边缘检测的要求较为类似,因此,可以实现一种具有广泛应用意义的边缘检测技术。边缘检测的一般标准包括:
以低的错误率检测边缘,也即意味着需要尽可能准确的捕获图像中尽可能多的边缘。
检测到的边缘应精确定位在真实边缘的中心。
图像中给定的边缘应只被标记一次,并且在可能的情况下,图像的噪声不应产生假的边缘。
为了满足这些要求,Canny使用了变分法。Canny检测器中的最优函数使用四个指数项的和来描述,它可以由高斯函数的一阶导数来近似。
在目前常用的边缘检测方法中,Canny边缘检测算法是具有严格定义的,可以提供良好可靠检测的方法之一。由于它具有满足边缘检测的三个标准和实现过程简单的优势,成为边缘检测最流行的算法之一。
完成一个Canny边缘检测算法可以分为以下四步:
2.1 高斯滤波
边缘检测非常容易受到图像噪声的影响,因此为了避免检测到错误的边缘信息,可以先用高斯滤波器去除图像噪声。
假设为src原图像,dst为高斯滤波后的图像,M为5×5的高斯卷积核(M不固定):(*表示卷积运算)
注意:选择高斯核的大小会影响检测器的性能。尺寸越大,检测器对噪声的灵敏度越低。此外,随着高斯滤波器核大小的增加,用于检测边缘的定位误差将略有增加。一般5×5的核是比较不错的。
2.2 计算梯度强度和方向
梯度的方向与边缘的方向总是垂直的。图像中的边缘可以指向各个方向,通常会取水平(左、右)、垂直(上、下)、对角线(左上、右上、左下、右下)等八个不同的方向计算梯度。
接下来使用边缘检测的算子(如Roberts,Sobel,Scharr等)来计算图像中的水平、垂直和对角方向的梯度。得到水平
和垂直
方向的一阶导数值,由此便可以确定像素点的梯度的大小
和方向
。
其中
为梯度大小,
表示梯度方向,
为反正切函数。通过上式我们可以得到一个具有梯度大小
和方向
的矩阵。如下图:
角度的确定
:
得到的角度一般不在前边指定的放个方向上,我们需要将角度分类到八个方向中。假设有四条线,分别是0,45,90,135度线(0度和180重合,是一条线)。需要对通过(2)式求出的
进行近似,分类到这四条线分成的八个区域中。
比如计算出的
,则应将其归类到
的区域,就是垂直向上方向。
八个区域如下图:
2.3 非极大值抑制(NMS)
在每一点上,邻域中心与沿着其对应的梯度方向的两个像素相比,若中心像素()为最大值,则保留,否则中心置0,这样可以抑制非极大值,保留局部梯度最大的点,以得到细化的边缘。
对图像进行梯度计算后,仅仅基于梯度值提取的边缘仍然很模糊。对边缘有且应当只有一个准确的响应。而非极大值抑制则可以帮助将局部最大值之外的所有梯度值抑制为0。非极大值抑制是一种边缘稀疏技术,非极大值抑制的作用在于“瘦”边。直观上地看,对第二步得到的图片,边缘由粗变细了。
经过上述处理后,对于同一个方向的若干边缘点,基本上只保留了一个,因此实现了边缘细化的目的。
如下图,A,B,C三点中,梯度方向上A点的局部梯度值最大,所以保留A点,其余两点被抑制。
2.4 用双阈值算法检测和连接边缘
经过上述步骤后,图像内的强边缘已经在当前获取的边缘内,但是,一些虚边缘也在内。
我们设置两个阈值,高阈值maxVal和低阈值minVal,根据当前边缘点的梯度值与这两个阈值的关系,判断边缘的属性:
对得到的虚边缘,再做以下处理:
可以肯定的是,强边缘必然是边缘点,因此必须将maxVal设置的足够高,以要求像素点的梯度值足够大(变化足够剧烈),而弱边缘可能是边缘,也可能是噪声,当虚边缘与强边缘相连时,就认为该虚边缘点是边缘点,以此来实现对强边缘的补充。
实际中maxVal:minVal=2:1的比例效果比较好,其中maxVal可以指定,也可以设计算法来自适应的指定,比如定义梯度直方图的前30%的分界线为maxVal。
三、基于OpenCV的实现
3.1 Sobel算子函数
OpenCV使用Sobel 算子的方法是cv2.Sobel()
dst = cv2.Sobel(src,ddepth,dx,dy,ksize,scale,delta,borderType)
参数:
src 原图像
ddepth 输出图像的深度,具体关系: