【OpenCV学习】图像梯度:Sobel算子、Scharr算子、Laplacian算子

图像梯度计算的是图像变化的速度。对于边缘部分,其灰度值变化较大,梯度值也较大;相反,较平滑的部分,灰度值变化较小,相应的梯度值也较小,一般情况时,图像梯度计算的是图像的边缘信息。
严格来讲,计算图像梯度需要求导数,但是图像梯度一般通过计算像素值的差来得到梯度的近似值(近似导数值)。
边界是指左侧的像素值与右侧的像素值差值不为零。

Sobel算子

Sobel算子是一种离散的微分算子,该算子结合了高斯平滑和微分求导运算。该算子利用局部查分寻找边缘,计算所得的是一个梯度的近似值。滤波器通常是指由一幅图像根据像素点(x,y)临近的区域计算得到另外一幅新图像的算法。因此,滤波器是由邻域及预定义的操作构成的。滤波器也被称为“掩模”、“核”、“模板”、“窗口”、“算子”等。信号领域称为滤波器,数学领域称其为核。“线性滤波器”滤波的目标像素点的值等于原始像素值及其周围像素值的加权和。这种基于线性核的滤波,就是我们所熟悉的卷积。sobel算子通常是指sobel滤波器。

水平方向上偏导数的近似值计算:
使用33大小的Sobel算子时,水平方向偏导数Gx的计算方式为
在这里插入图片描述
src为原始图像,假设有9个像素点:
在这里插入图片描述
计算像素点P5水平方向偏导数P5x,则需要利用Sobel算子及P5邻域点,公式为:
P5x=(P3-P1)+2
(P6-P4)+(P9-P7)

垂直方向偏导数的近似值:
将Sobel算子与原始图像src进行卷积计算,可以计算垂直方向上的变化情况,当Sobel算子的大小为3*3时,垂直方向偏导数Gy的计算方式为:
在这里插入图片描述

src为原始图像,假设其中有9个像素点:

在这里插入图片描述
要计算像素点P5垂直方向偏导数P5y,则需要利用Sobel算子及P5邻域点,所使用公式为:
P5y = (P7-P1)+2*(P8-P2)+(P9-P3)

Sobel算子及函数使用:
使用函数cv2.Sobel()实现Sobel算子运算,其语法形式为:

dst = cv2.Sobel(src, ddepth, dx, dy[,ksize[, scale[, delta[, borderType]]]])
  • dst代表目标函数
  • src代表原始图像
  • ddpeth代表输出图像的深度
  • dx代表x方向上的求导阶数
  • dy代表y方向上的求导阶数
  • ksize代表Sobel核的大小,该值为-1时,则会使用Scharr算子进行运算
  • scale代表计算导数时所采用的缩放因子,默认为1,无缩放
  • delta代表加在目标图像dst上的值,该值是可选的,默认为0
  • borderType代表边界样式

在实际操作中,计算梯度值可能会出现负数,为了避免信息丢失,在计算时使用更高的数据类型cv2.CV_64F,在通过取绝对值将其映射为cv2.CV_8U(8位图)类型。
使用函数cv2.convertScaleAbs()对参数取绝对值,该函数语法格式为:

dst = cv2.convertScaleAbs( src [, alpha[, beta]])
  • dst代表处理结果
  • src代表原始图像
  • alpha代表调节系数,默认为1
  • beta代表调节亮度值,默认为0

该函数可将原始图像src转变为356色位图,表示为:

dst = saturate(src*alpha+beta)

saturate()表示计算结果的最大值是饱和值。

示例程序:

import cv2
img = cv2.imread('dige.jpg')
sobelx = cv2.Sobel(img, cv2.CV_64F,1,0)
sobely = cv2.Sobel(img, cv2.CV_64F, 0,1)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv2.imshow('img',img)
cv2.imshow('sobelxy',sobelxy)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:
原始图像
在这里插入图片描述
sobelxy
在这里插入图片描述
由结果可以看出,sobel算子可以计算出图像的边界,程序中先将图片的x和y方向的边缘分别计算出来,并取绝对值,然后利用cv2.addWeighted()函数将两个方向的梯度合并,结果便是整幅图像所有的边缘信息。

两种方式获取图像两个方向的边缘信息:

  • 放式1:分别使用“dx=1,dy=0”和“dx=0,dy=1”计算图像在水平方向垂直方向的边缘信息,然后将二者相加,构成两个方向的边缘信息。
  • 方式2:将参数设置为“dx=1,dy=1”,获取图像在两个方向的梯度。

Scharr算子

Scharr算子可以被看做是对Sobel算子的改进,不仅具有和sobel算子同样的速度,且精度更高。Opencv提供了函数cv2.Scharr()来计算Scharr算子,语法如下:

dst = cv2.Scharr(src, ddepth, dx, dy[, scale[, delta[,borderType]]])
  • dst代表输出图像
  • src代表原始图像
  • ddepth代表输出图像深度
  • dx代表x方向上的导数阶数
  • dy代表y方向上的导数阶数
  • scale代表计算导数值时的缩放因子,默认值为1
  • delta代表加到目标图像上的亮度值,默认值为0
  • borderType代表边界样式。

在函数cv2.Sobel()中,如果ksize=-1,则会使用Scharr滤波器,因此语句:

dst = cv2.Scharr(src, ddepth, dx, dy)

dst = cv2.Sobel(src, ddepth, dx, dy, -1)

是等价的
函数cv2.Scharr()和函数cv2.Sobel()的使用方式一致
需要注意的是,参数ddepth的值应该设置为cv2.CV_64F,并对cv2.Scharr()的计算结果取绝对值,才能保证得到正确的处理结果。语句如下:

dst = Scharr(src, cv2.CV_64F, dx, dy)
dst = cv2.convertScaleAbs(dst)

Sobel算子和Scharr算子的比较

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

Laplacian算子

Laplacian(拉普拉斯)算子是一种二阶导数算子,其具有旋转不变性,可以满足不同方向的**图像边缘锐化(边缘检测)**的要求。
一个33大小的Laplacian算子如下所示:
在这里插入图片描述
Laplacian算子类似二阶Sobel导数,需要计算两个方向的梯度值。
在这里插入图片描述
计算像素点P5的近似到数值,如下:
P5lag = (P2+P4+P6+P8)-4
P5

计算结果的值可能为正,也可能为负。所以对计算结果取绝对值,以保证后续运算和显示都是正确的。

在Opencv使用函数cv2.Laplacian()实现Laplacian算子的计算,语法格式如下:

dst = cv2.Laplacian(src, ddepth[, ksize[, scale[, delte[, borderType]]]])
  • dst代表目标图像
  • src代表原始图像
  • ddepth代表目标图像的深度
  • ksize代表用于计算二阶导数的核尺寸大小,该值必须为正的奇数
  • scale代表计算Laplacian值的缩放比例因子,该参数是可选的,默认为1,表示不缩放
  • delta代表加到目标图像上的可选值,默认为0

示例代码:

import cv2
img = cv2.imread('opencv.jpg',cv2.IMREAD_GRAYSCALE)
laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)
cv2.imshow('img',img)
cv2.imshow('laplacian',laplacian)
cv2.waitKey()
cv2.destroyAllWindows()

结果如下:
原始图像
在这里插入图片描述
Laplacian的到的边缘信息
在这里插入图片描述

算子总结

Sobel算子、Scharr算子、Laplacian算子都可以用作边缘检测。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值