win10+Python3.7.3+OpenCV3.4.1入门学习(九、图像梯度)————9.4 Scharr算子及函数使用

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

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

OpenCV提供了函数cv2.Scharr()来计算Scharr算子,其语法格式如下:

dst = cv2.Scharr( src, ddepth, dx, dy[, scale[, delta[, borderType]]] )

式中:
● dst代表输出图像。
● src代表原始图像。
● ddepth代表输出图像深度。该值与函数cv2.Sobel()中的参数ddepth的含义相同,具体可以参考表9-1。
● dx代表x方向上的导数阶数。
● dy代表y方向上的导数阶数。
● scale代表计算导数值时的缩放因子,该项是可选项,默认值是1,表示没有缩放。
● delta代表加到目标图像上的亮度值,该项是可选项,默认值为0。
● borderType代表边界样式。具体可以参考表9-2。
在函数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)

另外,需要注意的是,在函数cv2.Scharr()中,要求参数dx和dy满足条件:

dx >= 0 && dy >= 0 && dx+dy == 1

因此,参数dx和参数dy的组合形式有:
● 计算x方向边缘(梯度):dx=1, dy=0。
● 计算y方向边缘(梯度): dx=0, dy=1。
● 计算x方向与y方向的边缘叠加:通过组合方式实现。
下面分别对上述情况进行简要说明。
1.计算x方向边缘(梯度):dx=1, dy=0
此时,使用的语句是:

dst=Scharr(src, ddpeth, dx=1, dy=0)

2.计算y方向边缘(梯度):dx=0, dy=1
此时,使用的语句是:

dst=Scharr(src, ddpeth, dx=0, dy=1)

3.计算x方向与y方向的边缘叠加
将两个方向的边缘相加,使用的语句是:

dx=Scharr(src, ddpeth, dx=1, dy=0)
Scharr(src, ddpeth, dx=0, dy=1)
Scharrxy=cv2.addWeighted(dx,0.5, dy,0.5,0)

需要注意的是,参数dx和dy的值不能都为1。例如,如下语句是错误的:

dst=Scharr(src, ddpeth, dx=1, dy=1)

eg1:使用函数cv2.Scharr()获取图像水平方向的边缘信息。
程序如下:

import cv2
o = cv2.imread('scharr.bmp',cv2.IMREAD_GRAYSCALE)
scharrx = cv2.Scharr(o,cv2.CV_64F,1,0)
scharrx = cv2.convertScaleAbs(scharrx)   # 转回uint8  
cv2.imshow("original",o)
cv2.imshow("x",scharrx)
cv2.waitKey()
cv2.destroyAllWindows()

运行程序,结果如下图所示。
在这里插入图片描述在这里插入图片描述

eg2:使用函数cv2.Scharr()获取图像垂直方向的边缘信息。
:程序如下:

import cv2
o = cv2.imread('scharr.bmp',cv2.IMREAD_GRAYSCALE)
scharry = cv2.Scharr(o,cv2.CV_64F,0,1)
scharry = cv2.convertScaleAbs(scharry)  
cv2.imshow("original",o)
cv2.imshow("y",scharry)
cv2.waitKey()
cv2.destroyAllWindows()

运行程序,结果如下图所示。
在这里插入图片描述在这里插入图片描述
eg3:使用函数cv2.Scharr()实现水平方向和垂直方向边缘叠加的效果。
程序如下:

import cv2
o = cv2.imread('scharr.bmp',cv2.IMREAD_GRAYSCALE)
scharrx = cv2.Scharr(o,cv2.CV_64F,1,0)
scharry = cv2.Scharr(o,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx)   # 转回uint8  
scharry = cv2.convertScaleAbs(scharry)  
scharrxy =  cv2.addWeighted(scharrx,0.5,scharry,0.5,0)  
cv2.imshow("original",o)
cv2.imshow("xy",scharrxy)
cv2.waitKey()
cv2.destroyAllWindows()

运行程序,结果如下图所示。
在这里插入图片描述在这里插入图片描述
eg4:观察函数cv2.Scharr()的参数 dx、dy同时设置为1时,程序的运行情况。
:程序如下:

import cv2
o = cv2.imread('scharr.bmp',cv2.IMREAD_GRAYSCALE)
scharrxy11=cv2.Scharr(o,cv2.CV_64F,1,1)
cv2.imshow("original",o)
cv2.imshow("xy11",scharrxy11)
cv2.waitKey()
cv2.destroyAllWindows()

运行程序,报错如下:

cv2.error: OpenCV(3.4.1) C:\Miniconda3\conda-bld\opencv-suite_1533128839831\work\modules\imgproc\src\deriv.cpp:67: error: (-215) dx >= 0 && dy >= 0 && dx+dy == 1 in function cv::getScharrKernels

【分析】需要注意,不允许将函数cv2.Scharr()的参数dx和dy的值同时设置为1。因此,本例中将这两个参数的值都设置为1后,程序会报错。

【例9.12】使用函数cv2.Sobel()完成Scharr算子的运算。
当函数cv2.Sobel()中ksize的参数值为-1时,就会使用Scharr算子进行运算。因此,

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

等价于

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

程序如下:

import cv2
o = cv2.imread('sobel4.bmp',cv2.IMREAD_GRAYSCALE)
scharrx = cv2.Sobel(o,cv2.CV_64F,1,0,-1)
scharry = cv2.Sobel(o,cv2.CV_64F,0,1,-1)
scharrx = cv2.convertScaleAbs(scharrx)   # 转回uint8  
scharry = cv2.convertScaleAbs(scharry) 
cv2.imshow("original",o)
cv2.imshow("x",scharrx)
cv2.imshow("y",scharry)
cv2.waitKey()
cv2.destroyAllWindows()

运行程序,结果如下图所示,其中左图为原始图像,中间的图为水平边缘图像,右图为垂直边缘图像。

在这里插入图片描述在这里插入图片描述在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值