简介:

​         图像梯度计算的是图像变化的幅度。对于图像的边缘部分,其灰度值变化较大,梯度值变化也较大;相反,对于图像中比较平滑的部分,其灰度值变化较小,相应的梯度值变化也较小。一般情况下,图像梯度计算的是图像的边缘信息。它在图像处理和计算机视觉中具有重要的应用,常用于边缘检测、特征提取和图像增强等任务。

图像梯度概念:

图像梯度就是对图像的X轴,Y轴求其变化率,是一个二维的向量,分别表示X轴的变化和Y轴的变化:

其中:

  • X轴的变化是指当前像素右侧(X加1)的像素值减去当前像素左侧(X减1)的像素值。
  • Y轴的变化是当前像素下方(Y加1)的像素值减去当前像素上方(Y减1)的像素值。

 将计算出来的两个分量合并在一起,形成一个二维向量就得到了图像梯度。

推导:

首先我们先来看一下数学知识微积分的求导的过程:

\frac{df}{dx}=\lim_{\varepsilon \rightarrow 0}\frac{f\left ( x+\varepsilon \right )-f\left ( x \right )}{\varepsilon }

这里是对图像的一阶微分,但是图像时一个二维的向量,假设我们设该函数为f(x,y),我们看一下微积分中对两个未知数的微分,这里就是求偏导的内容

对x方向的求导:

\frac{\partial f\left ( x,y \right ) }{\partial x}=\lim_{\varepsilon \to 0}\frac{f\left ( x+\varepsilon ,y \right )-f\left ( x,y \right )}{\varepsilon }

对y方向的求导:

\frac{\partial f\left ( x,y \right ) }{\partial y}=\lim_{\varepsilon \to 0}\frac{f\left ( x ,y+\varepsilon \right )-f\left ( x,y \right )}{\varepsilon }

这里求导,高数的知识说\varepsilon这个值应该趋近于0,这样才能求的偏导,也就是\varepsilon无限小,但是对于图像来说\varepsilon取不到很小的值,图像中的像素离散的,最小的距离应为1。因此这里我们令\varepsilon等于1。那么上面的公式就变为:

\frac{\partial f(x,y)}{\partial x}=f(x+1,y)-f(x,y)

\frac{\partial f(x,y)}{\partial y}=f(x,y+1)-f(x,y)

这样我们就得到了图像的梯度公式,仔细观察我们可以看到图像梯度可以近似为相邻像素的差值。

上述两个公式对所有 x 和 y 的有关值可用下图的一维模板对 f(x,y) 的滤波得到。

用于计算梯度偏导数的滤波器模板,通常称之为梯度算子边缘算子边缘检测子等。

对于不同的滤波器模板得到的梯度是不同的,这也就衍生出很多算子,如Roberts、Prewitt、Sobel和Laplacian算子等。下面将详细介绍不同的算子。

梯度算子

梯度简单来说就是求导。OpenCV 提供了三种不同的梯度滤波器,或者说高通滤波器:Sobel Scharr 和Laplacian 。什么叫高通呢?其实就是和图像模糊相反。图像模糊是让低频通过,阻挡高频,这样就可以去除噪点,让锐利的边缘变平滑。高通滤波器就是让高频通过,阻挡低频,可以让边缘更加明显,增强图像。

Roberts 算子:

Roberts算子即交叉微分算子,是基于交叉差分的梯度算子。此算法通过局部差分来计算检测图像的边缘线条,对噪声敏感

Roberts交叉微分算子分别为主对角线和副对角线方向的算子,有两个2*2的滤波算子组成:

Prewitt 算子:

Prewitt算子是一种图像边缘检测的微分算子,其原理是利用特定区域内像素灰度值产生的差分实现边缘检测。由于Prewitt算子采用 33 模板对区域内的像素值进行计算,而Robert算子的模板为 22,故Prewitt算子的边缘检测结果在水平方向和垂直方向均比Robert算子更加明显。Prewitt算子适合用来识别噪声较多、灰度渐变的图像,其计算公式如下所示:

例如,下面给出Prewitt算子模板,在像素点P5处 x 和 y 方向上的梯度大小分别计算为:

Prewitt算子的边缘检测结果在水平方向和垂直方向均比Robert算子更加明显。

Sobel算子:

 Sobel算子,主要用作边缘检测,是离散差分算子,用来运算图像梯度函数的灰度近似值。Sobel算子具有一定的平滑作用,对噪声不敏感。在图像的任何一点使用此算子,将会产生对应的梯度矢量或者法矢量。其中Sobel算子x轴y轴卷积核如下:

如上图我们可以看到对P5这个点求x轴,y轴的梯度。以Gx为例,P5的x轴梯度公式是:

P5  = (P3-P1)+2(P6-P4)+(P9-P7)

 这里我们可以看到,由于P6和P4距离P5较近,对P5的影响较大,所以给予了一个较大的权重2,从差值中我们可以看到,P5右边的值减去P5左边的值,假设两边差值较大说明P5这个点位于边界,两边差值较小,说明P5在图像变化较为平缓区域。

下面我们使用python代码对其实现:

# coding:utf-8
import cv2
import numpy as np


# Scharr算子实现梯度计算
def Scharr_demo(image):
    # x 方向梯度
    image_grad_x = cv2.Sobel(image, cv2.CV_32F, 1, 0)
    # y 方向梯度
    image_grad_y = cv2.Sobel(image, cv2.CV_32F, 0, 1)
    # 分别求绝对值并转化为8位的图像上,这样做方便显示
    image_gradx = cv2.convertScaleAbs(image_grad_x)
    image_grady = cv2.convertScaleAbs(image_grad_y)
    # 显示两个方向图像
    cv2.imshow("image_gradient-x", image_gradx)
    cv2.imshow("image_gradient-y", image_grady)

    # 两个方向梯度的叠加,权重各自一半
    image_gradxy = cv2.addWeighted(image_gradx, 0.5, image_grady, 0.5, 0)
    cv2.imshow("image_gradient", image_gradxy)


if __name__ == '__main__':
    image = cv2.imread("a.jpg")
    cv2.imshow("src_image", image)
    Scharr_demo(image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

这里我们使用第一张图进行求图像梯度结果图如下:

Scharr算子:

​ 在离散的空间上,有很多方法可以用来计算近似导数,在使用3×3的Sobel算子时,可能计算结果并不太精准。下面我们介绍Scharr算子,该算子具有和Sobel算子同样的速度,且精度更高。可以将Scharr算子看作对Sobel算子的改进,其核通常为:

梯度的计算方法与Sobel算子一样,下面我们使用Python对其进行实现:

#coding:utf-8
import cv2 
import numpy as np
 
 
# Scharr算子实现梯度计算
def Scharr_demo(image):
    # x 方向梯度
    image_grad_x = cv2.Scharr(image, cv2.CV_32F, 1, 0)
    # y 方向梯度
    image_grad_y = cv2.Scharr(image, cv2.CV_32F, 0, 1)
    # 分别求绝对值并转化为8位的图像上,这样做方便显示
    image_gradx = cv2.convertScaleAbs(image_grad_x) 
    image_grady = cv2.convertScaleAbs(image_grad_y)
    # 显示两个方向图像
    cv2.imshow("image_gradient-x", image_gradx)
    cv2.imshow("image_gradient-y", image_grady)
 
 
    #两个方向梯度的叠加,权重各自一半
    image_gradxy = cv2.addWeighted(image_gradx, 0.5, image_grady, 0.5, 0)
    cv2.imshow("image_gradient", image_gradxy)
 
 
 
 
 
 
if __name__ == '__main__':
    image = cv2.imread("./test01.jpg")
    cv2.imshow("src_image", image)
    Scharr_demo(image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
 
 

这里我们依旧使用第一张图进行求图像梯度结果图如下:

Sobel算子与Scharr算子比较:

Sobel算子的缺点是,当其核结构较小时,精确度不高,而Scharr算子具有更高的精度。

下面我们对两个算子对图像处理的结果进行展示:

这里第一张为原始图像,第二张是通过Sobel求图像梯度,第三张是通过Scharr算子求图像梯度。

 Laplacian 算子: 

Laplacian(拉普拉斯)算子是一种二阶导数算子,其具有旋转不变性,可以满足不同方向的图像边缘锐化(边缘检测)的要求。通常情况下,其算子的系数之和需要为零。例如,一个
3×3 大小的 Laplacian 算子如图 所示。

Laplacian 算子类似二阶 Sobel 导数,需要计算两个方向的梯度值。

为了更适合于数字图像处理,将该方程表示为离散形式:

另外,拉普拉斯算子还可以表示成模板的形式,以便更好编程需要。如下图所示。

图(a)表示离散拉普拉斯算子的模板,图(b)表示其扩展模板,图(c)则分别表示其他两种拉普拉斯的实现模板。从模板形式容易看出,如果在图像中一个较暗的区域中出现了一个亮点,那么用拉普拉斯运算就会使这个亮点变得更亮。因为图像中的边缘就是那些灰度发生跳变的区域,所以拉普拉斯锐化模板在边缘检测中很有用。一般增强技术对于陡峭的边缘和缓慢变化的边缘很难确定其边缘线的位置。但此算子却可用二次微分正峰和负峰之间的过零点来确定,对孤立点或端点更为敏感,因此特别适用于以突出图像中的孤立点、孤立线或线端点为目的的场合。同梯度算子一样,拉普拉斯算子也会增强图像中的噪声,有时用拉普拉斯算子进行边缘检测时,可将图像先进行平滑处理。

图像锐化处理的作用是使灰度反差增强,从而使模糊图像变得更加清晰。图像模糊的实质就是图像受到平均运算或积分运算,因此可以对图像进行逆运算,如微分运算能够突出图像细节,使图像变得更为清晰。由于拉普拉斯是一种微分算子,它的应用可增强图像中灰度突变的区域,减弱灰度的缓慢变化区域。因此,锐化处理可选择拉普拉斯算子对原图像进行处理,产生描述灰度突变的图像,再将拉普拉斯图像与原始图像叠加而产生锐化图像。拉普拉斯锐化的基本方法可以由下式表示:

这种简单的锐化方法既可以产生拉普拉斯锐化处理的效果,同时又能保留背景信息,将原始图像叠加到拉普拉斯变换的处理结果中去,可以使图像中的各灰度值得到保留,使灰度突变处的对比度得到增强,最终结果是在保留图像背景的前提下,突现出图像中小的细节信息。但其缺点是对图像中的某些边缘产生双重响应。

 各类算子的优缺点:

(1)Roberts 算子 

Roberts算子利用局部差分算子寻找边缘,边缘定位精度较高,但容易丢失一部分边缘,不具备抑制噪声的能力。该算子对具有陡峭边缘且含噪声少的图像效果较好,尤其是边缘正负45度较多的图像,但定位准确率较差;

(2) Prewitt 算子

Prewitt算子对灰度渐变的图像边缘提取效果较好,而没有考虑相邻点的距离远近对当前像素点的影响,与Sobel 算子类似,不同的是在平滑部分的权重大小有些差异;

(3)Sobel 算子

Sobel算子考虑了综合因素,对噪声较多的图像处理效果更好,Sobel 算子边缘定位效果不错,但检测出的边缘容易出现多像素宽度。

(4)Scharr算子

Scharr算子,该算子具有和Sobel算子同样的速度,且精度更高。可以将Scharr算子看作对Sobel算子的改进。

(5)Laplacian 算子

Laplacian 算子不依赖于边缘方向的二阶微分算子,对图像中的阶跃型边缘点定位准确,该算子对噪声非常敏感,它使噪声成分得到加强,这两个特性使得该算子容易丢失一部分边缘的方向信息,造成一些不连续的检测边缘,同时抗噪声能力比较差,由于其算法可能会出现双像素边界,常用来判断边缘像素位于图像的明区或暗区,很少用于边缘检测。
 

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐