6.图像梯度

本文介绍了OpenCV中用于图像梯度计算的方法,包括Sobel和Scharr导数以及Laplacian导数。Sobel算子结合了高斯平滑和微分,Scharr滤波器在3x3尺寸下提供更准确结果。Laplacian算子通过Sobel导数计算图像的拉普拉斯算子。对于边缘检测,建议使用更高精度的数据类型以避免负值丢失。
摘要由CSDN通过智能技术生成

查找图像渐变、边缘等
使用到以下方法 : cv.Sobel(), cv.Scharr(), cv.Laplacian()…

原理

OpenCV 提供了三种类型的梯度滤波器或高通滤波器,Sobel、Scharr 和 Laplacian。

1. Sobel 和 Scharr 导数

Sobel算子是联合高斯平滑加微分运算,所以更抗噪。您可以指定要采用的导数的方向,垂直或水平(分别通过参数 yorder 和 xorder)。您还可以通过参数 ksize 指定内核的大小。如果 ksize = -1,则使用 3x3 Scharr 过滤器,其结果比 3x3 Sobel 过滤器更好。请参阅所用内核的文档。

1.1 Sobel()方法

在除一种情况之外的所有情况下,ksize×ksize 可分离核用于计算导数。当ksize = 1时,使用3×1或1×3核(即不做高斯平滑)。 ksize = 1 只能用于一阶或二阶 x 或 y 导数。

还有一个特殊值 ksize = FILTER_SCHRR (-1) 对应于 3×3 Scharr 过滤器,它可能给出比 3×3 Sobel 更准确的结果。shcarr为:
[ − 3 0 3 − 10 0 10 − 3 0 3 ] (1) \begin{bmatrix} -3&0&3\\ -10&0&10\\ -3&0&3\\ \end{bmatrix}\tag{1} 31030003103(1)
该函数通过使用适当的内核对图像进行卷积来计算图像导数:
d s s t = ∂ x o r d e r + y o r d e r s r c ∂ x x o r d e r ∂ y y o r d e r dsst=\frac{∂^{xorder}+y^{order}src}{∂x^{xorder}∂y^{yorder}} dsst=xxorderyyorderxorder+yordersrc
Sobel 算子结合了高斯平滑和微分,因此结果或多或少地抵抗噪声。大多数情况下,使用 ( xorder = 1, yorder = 0, ksize = 3) 或 ( xorder = 0, yorder = 1, ksize = 3) 调用该函数来计算第一个 x 或 y 图像导数。第一种情况对应于以下内核:
[ − 1 0 1 − 2 0 2 − 1 0 2 ] (2) \begin{bmatrix} -1&0&1\\ -2&0&2\\ -1&0&2\\ \end{bmatrix}\tag{2} 121000122(2)
第二种情况对应于以下内核:
[ − 1 − 2 − 1 0 0 0 1 2 1 ] (3) \begin{bmatrix} -1&-2&-1\\ 0&0&0\\ 1&2&1\\ \end{bmatrix}\tag{3} 101202101(3)
python中的用法:

	dst	=	cv.Sobel(	src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]	)
参数描述
src输入图片矩阵
dst输出图片矩阵
ddepth图像深度
dx导数x的阶数
dy导数y的阶数
ksize扩展 Sobel 核的大小;它必须是 1、3、5 或 7
scale缩放尺度
delta在将结果存储到 dst 之前添加到结果中的可选增量值。
borderType像素拓展方法,参见 BorderTypes。不支持 BORDER_WRAP。
1.2shcarr()方法
Scharr(src, dst, ddepth, dx, dy, scale, delta, borderType)

相当于

Sobel(src, dst, ddepth, dx, dy, FILTER_SCHARR, scale, delta, borderType).

2. Laplacian 导数

它计算由关系给出的图像的拉普拉斯算子 Δ s r c = ∂ 2 s r c ∂ x 2 + ∂ 2 s r c ∂ y 2 Δsrc=\frac{∂2src}{∂x2}+\frac{∂2src}{∂y2} Δsrc=x22src+y22src这是在ksize>1时进行的,其中每个导数都是使用 Sobel 导数找到的。如果 ksize = 1,则使用以下内核进行过滤:

k e r n e l = [ 0 1 0 1 − 4 1 0 1 0 ] (4) kernel = \begin{bmatrix} 0&1&0\\ 1&-4&1\\ 0&1&0\\ \end{bmatrix}\tag{4} kernel=010141010(4)
python中用法:

	dst	=	cv.Laplacian(	src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]]	)

参数描述
src输入图片矩阵
dst输出图片矩阵
ddepth图像深度
ksize用于计算二阶导数滤波器的孔径大小。大小必须是正数和奇数。
scale计算的拉普拉斯值的可选比例因子。默认情况下,不应用缩放。
delta可选的delta值,在将结果存储到dst之前,将其添加到结果中。
borderType像素拓展方法,参见 BorderTypes。不支持 BORDER_WRAP。
img = cv.imread("../../file/photos/dave.jpg", 0)
# ksize = 9 是最好的效果
laplacian = cv.Laplacian(img, cv.CV_64F, ksize=9)
sobelx = cv.Sobel(img, cv.CV_8U, 1, 0, ksize=-1)
sobely = cv.Sobel(img, cv.CV_8U, 0, 1, ksize=5)
plt.subplot(2, 2, 1), plt.imshow(img, cmap='gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(2, 2, 2), plt.imshow(laplacian, cmap='gray')
plt.title('Laplacian'), plt.xticks([]), plt.yticks([])
plt.subplot(2, 2, 3), plt.imshow(sobelx, cmap='gray')
plt.title('Sobel X'), plt.xticks([]), plt.yticks([])
plt.subplot(2, 2, 4), plt.imshow(sobely, cmap='gray')
plt.title('Sobel Y'), plt.xticks([]), plt.yticks([])
plt.show()

结果如下,Lapalacian结果和官方文档结果不同
在这里插入图片描述
在最后一个示例中,输出数据类型是 cv.CV_8U 或 np.uint8。但这有一个小问题。黑到白过渡被视为正斜率(它具有正值),而白到黑过渡被视为负斜率(它具有负值)。因此,当您将数据转换为 np.uint8 时,所有负斜率都为零。简而言之,你错过了那个边缘,如果你想检测两个边缘,更好的选择是将输出数据类型保持为更高的形式,如 cv.CV_16S、cv.CV_64F 等,取其绝对值,然后转换回 cv.CV_8U。下面的代码演示了水平 Sobel 滤波器的此过程和结果差异。

img = cv.imread("../../file/photos/box1.jpg", 0)
sobelx8u = cv.Sobel(img, -1, 1, 0, ksize=3)
sobelx64f = cv.Sobel(img, cv.CV_64F, 1, 0, ksize=3)
abs_sobel64f = np.abs(sobelx64f)  # 对其求绝对值
sobel_8u = np.uint8(abs_sobel64f)  # 将绝对值转换成uint8

结果如下
在这里插入图片描述

depth类型

Input depth (src.depth())Output depth (ddepth)
CV_8U-1/CV_16S/CV_32F/CV_64F
CV_16U/CV_16S-1/CV_32F/CV_64F
CV_32F-1/CV_32F/CV_64F
CV_64F-1/CV_64F
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值