图像梯度
0 引言
参考书籍 《OpenCV轻松入门——面向Python》李立宗著,电子工业出版社出版
图像梯度计算的计算图像变化的速度。
对于图像的边缘部分,其灰度值变化较大,梯度值也较大;相反,对于图像中比较平滑的部分,其灰度值变化较小,相应的梯度值也较小。
一般来说,图像梯度计算的是图像的边缘信息。
1 Sobel理论基础
Sobel算子是一种离散的微分算子,该算子结合了高斯平滑和微分求导运算。
该算子利用局部差分寻找边缘,计算所得的是一个梯度的近似值。
Sobel算子如图1所示。
水平方向:
垂直方向:
需要说明的是,滤波器通常是指由一幅图像根据像素点(x,y)临近的区域计算得到另外一幅新图像的算法。因此,滤波器是由邻域及其预定义的操作构成的。滤波器规定了滤波所采用的形状以及该区域内像素值的组成规律。
滤波器也被称为“掩模”、“核”、“模板”、“窗口”、“算子”等等。也就是说,滤波的目标像素点的值等于原始像素值及其周围像素值的加权和。
如图,计算水平方向与垂直方向的偏导数。
1、水平方向
计算像素点P5的水平方向偏导数P5x,则需利用Sobel算子及P5邻域点,所使用的公式为:
P 5 x = ( P 3 − P 1 ) + ( P 6 − P 4 ) + ( P 9 − P 7 ) P5x=(P3-P1)+(P6-P4)+(P9-P7) P5x=(P3−P1)+(P6−P4)+(P9−P7)
即用像素点P5右侧像素点的像素值减去其左侧像素点的像素值。其中,中间像素点(P4和P6)距像素点P5较近,其像素值差值的权重为2;其余差值的权重为1。
2、垂直方向
计算像素点P5的水平方向偏导数P5y,则需利用Sobel算子及P5邻域点,所使用的公式为:
P 5 y = ( P 7 − P 1 ) + ( P 68 − P 2 ) + ( P 9 − P 3 ) P5y=(P7-P1)+(P68-P2)+(P9-P3) P5y=(P7−P1)+(P68−P2)+(P9−P3)
即用像素点P5下一行像素点的像素值减去其上一行像素点的像素值。其中,中间像素点(P2和P8)距像素点P5较近,其像素值差值的权重为2;其余差值的权重为1。
2 Sobel算子及函数使用
在OpenCV内,使用函数cv2.Sobel()实现Sobel算子运算,其语法形式为:
dst = cv2.Sobel(src,ddepth,dx,dy[,ksize[,scale[,delta[,borderType]]]])
# 式中,dst代表目标图像
# src代表原始图像。
# ddepth代表输出的图像深度。
# dx代表x方向上的求导阶数。
# dy代表y方向上的求导阶数。
# ksize代表Sobel核的大小。该值为-1时,则会使用Scharr算子进行运算。
# scale代表计算导数时的缩放因子,默认情况下为1,是没有缩放的。
# delta代表加在目标图像dst上的值,该值是可选的,默认为0.
# borderType代表边界样式。
2.1 参数ddepth
在函数cv2.Sobel()的语法中规定,可以将函数cv2.Sobel()内ddepth参数的值设为-1,让处理结果与原始图像保持一致。但是,如果直接将参数ddepth的值设置为1,在计算时的带的结果可能是错误的。
在实际操作中,计算的梯度值可能会出现负数。如果处理的图像是8位图类型,则在ddepth的参数值为-1时,意味着指定运算结果也是8位图类型,那么所有的负数会自动截断为0,发生信息丢失。
为了避免信息丢失,在计算时要先使用更高的数据类型cv2.CV_64F,再通过取绝对值将其映射为cv2.CV_8U(8位图)。所以通常要将函数cv2.Sobel()内ddepth参数的值设为“cv2.CV_64F”。
在OpenCV中,使用函数cv2.convertScaleAbs()对参数取绝对值,该函数的语法格式为:
dst = cv2.convertScaleAbs