win10+Python3.7.3+OpenCV3.4.1入门学习(九)————9.2 Sobel算子函数使用

Python版本是Python3.7.3,OpenCV版本OpenCV.3.4.1,开发环境为PyCharm

9.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 代表边界样式。该参数的具体类型及值如下表所示。
在这里插入图片描述

9.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”。
下面对参数ddepth值的设定做一个简要的说明。
例如,下图中的原始图像(左图)是一幅二值图像,图中黑色部分的像素值为0,白色部分的像素值为1。在计算A线条所在位置和B线条所在位置的近似偏导数时:
● 针对A线条所在列,右侧像素值减去左侧像素值所得近似偏导数的值为-1。
● 针对B线条所在列,右侧像素值减去左侧像素值所得近似偏导数的值为1。
针对上述偏导数结果进行不同方式的处理,可能会得到不同的结果,例如:
● 直接计算。此时,A线条位置的值为负数,B线条位置的值为正数。在显示时,由于上述负值不在8位图范围内,因此要做额外处理。将A线条处的负数偏导数处理为0, B线条处的正数偏导数保持不变。在这种情况下,显示结果如下图中间的图所示。
● 计算绝对值。此时,A线条处的负数偏导数被处理正数,B线条处的正数偏导数保持不变。在显示时,由于上述值在8位图的表示范围内,因此不再对上述值进行处理,此时,显示结果如下图中的右图所示。
在这里插入图片描述

上述问题在计算垂直方向的近似偏导数时同样存在。例如,下图中的原始图像(左图)是一幅二值图像,图中黑色部分的像素值为0,白色部分的像素值为1。计算A线条所在位置和B线条所在位置的近似偏导数时:
● 针对A线条所在行,下方像素值减去上方像素值所得近似偏导数为-1。
● 针对B线条所在行,下方像素值减去上方像素值所得近似偏导数为1。
针对上述偏导数结果进行不同方式的处理,可能会得到不同的结果,例如:
● 直接计算。此时,A线条位置的值为负数,B线条位置的值为正数。在显示时,上述值不在8位图的表示范围内,因此需要进行额外处理。将A线条处的负数偏导数处理为0, B线条处的正数偏导数保持不变。此时,显示结果如图中间的图所示。
● 计算绝对值。此时,A线条处的负数偏导数被处理正数,B线条处的正数偏导数保持不变。在显示时,由于上述值在8位图的表示范围内,因此不再对上述值进行处理,此时,显示结果如图中的右图所示。

在这里插入图片描述
经过上述分析可知,为了让偏导数正确地显示出来,需要将值为负数的近似偏导数转换为正数。即,要将偏导数取绝对值,以保证偏导数总能正确地显示出来。
例如,下图描述了如何计算偏导数。
在这里插入图片描述

为了得到结果为正数的偏导数,需要对图中计算的偏导数取绝对值,如下:
|P5x| = |(P3-P1) + 2*(P6-P4) + (P9-P7)|
|P5y| = |(P7-P1) + 2*(P8-P2) + (P9-P3)|

当然,在需要时,还可以进行如下处理:
P5Sobel = |P5x| + |P5y| = |(P3-P1) +2*(P6-P4) + (P9-P7)| + |(P7-P1) + 2*(P8-P2) + (P9-P3)|

经过以上分析,我们得知:在实际操作中,计算梯度值可能会出现负数。通常处理的图像是8位图类型,如果结果也是该类型,那么所有负数会自动截断为0,发生信息丢失。所以,为了避免信息丢失,我们在计算时使用更高的数据类型cv2.CV_64F,再通过取绝对值将其映射为cv2.CV_8U(8位图)类型。
在OpenCV中,使用函数cv2.convertScaleAbs()对参数取绝对值,该函数的语法格式为:

dst = cv2.convertScaleAbs( src [, alpha[, beta]] )

上式中:
● dst代表处理结果。
● src代表原始图像。
● alpha代表调节系数,该值是可选值,默认为1。
● beta代表调节亮度值,该值是默认值,默认为0。
这里,该函数的作用是将原始图像src转换为256色位图,其可以表示为:

dst=saturate(src*alpha+beta)

式中,saturate()表示计算结果的最大值是饱和值,例如当“src*alpha+beta”的值超过255时,其取值为255。

eg1:使用函数cv2.convertScaleAbs()对一个随机数组取绝对值。
代码如下:

import cv2
import numpy as np
img=np.random.randint(-256,256,size=[4,5],dtype=np.int16)
rst=cv2.convertScaleAbs(img)
print("img=\n",img)
print("rst=\n",rst)

运行程序,结果为:

img=
 [[-209   71 -217   74 -146]
 [ 217 -116   98   93   76]
 [  80  232  158 -232   17]
 [-152 -183  243   77 -177]]
rst=
 [[209  71 217  74 146]
 [217 116  98  93  76]
 [ 80 232 158 232  17]
 [152 183 243  77 177]]
9.2.2 方向

在函数cv2.Sobel()中,参数dx表示x轴方向的求导阶数,参数dy表示y轴方向的求导阶数。参数dx和dy通常的值为0或者1,最大值为2。如果是0,表示在该方向上没有求导。当然,参数dx和参数dy的值不能同时为0。参数dx和参数dy可以有多种形式的组合,主要包含:
● 计算x方向边缘(梯度):dx=1, dy=0。
● 计算y方向边缘(梯度):dx=0, dy=1。
● 参数dx与参数dy的值均为1:dx=1, dy=1。
● 计算x方向和y方向的边缘叠加:通过组合方式实现。
下面分别对上述情况进行简要说明。
1.计算x方向边缘(梯度):dx=1, dy=0
如果想只计算x方向(水平方向)的边缘,需要将函数cv2.Sobel()的参数dx和dy的值设置为“dx=1, dy=0”。当然,也可以设置为“dx=2, dy=0”。此时,会仅仅获取水平方向的边缘信息,此时的语法格式为:

dst = cv2.Sobel( src , ddepth , 1 , 0 )

使用该语句获取边缘图的示例如下图所示,其中左图为原始图像,右图为获取的边缘图。
在这里插入图片描述

2.计算y方向边缘(梯度):dx=0, dy=1
如果想只计算y方向(垂直方向)的边缘,需要将函数cv2.Sobel()的参数dx和dy的值设置为“dx=0, dy=1”。当然,也可以设置为“dx=0, dy=2”。此时,会仅仅获取垂直方向的边缘信息,此时的语法格式为:

dst = cv2.Sobel( src , ddepth , 0 , 1 )

使用该语句获取边缘图的示例如下图所示,其中左图为原始图像,右图为获取的边缘图。

在这里插入图片描述
3.参数dx与参数dy的值均为1:dx=1, dy=1
可以将函数cv2.Sobel()的参数dx和dy的值设置为“dx=1, dy=1”,也可以设置为“dx=2, dy=2”,或者两个参数都不为零的其他情况。此时,会获取两个方向的边缘信息,此时的语法格式为:

dst = cv2.Sobel( src , ddepth , 1 , 1 )

使用该语句获取边缘图的示例如下图所示,其中左图为原始图像,右图为获取的边缘图,仔细观察可以看到图中仅有若干个微小白点,每个点的大小为一个像素。
在这里插入图片描述

4.计算x方向和y方向的边缘叠加
如果想获取x方向和y方向的边缘叠加,需要分别获取水平方向、垂直方向两个方向的边缘图,然后将二者相加。此时的语法格式为:

dx= cv2.Sobel( src , ddepth , 1 , 0 )
dy= cv2.Sobel( src , ddepth , 0 , 1 )
dst=cv2.addWeighted( src1 , alpha , src2 , beta , gamma )

使用上述语句获取边缘图的示意图如下图所示,其中左图为原始图像,右图为获取的边缘图。

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值