如何使用np.gradient模仿cv2.Sobel?

How to mimic cv2.Sobel using np.gradient?

我想得到x轴和y轴方向的图像。但是,我想使用 np.gradient 函数进行编码,而不使用 cv2.Sobel 过滤器。

所以,我想像这样转换代码

x_grad = cv2.Sobel(image1, cv2.CV_64F, 1, 0, ksize=5)

像这样

x_grad = np.gradient(image1, axis=0)

但是,数值不一样。我该如何解决?

np.gradient has limited functionality, and only a few cases of cv2.Sobel 可以以某种方式复制,即:

import cv2
import numpy as np

image = cv2.imread('path/to/your/image.png', cv2.IMREAD_GRAYSCALE)

grad_cv2 = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=1)
grad_np = 2 * np.gradient(image, axis=1)
grad_np[:, [0, -1]] = 0
print(np.all(grad_cv2 == grad_np))
# True

grad_cv2 = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=1)
grad_np = 2 * np.gradient(image, axis=0)
grad_np[[0, -1], :] = 0
print(np.all(grad_cv2 == grad_np))
# True

grad_cv2 = cv2.Sobel(image, cv2.CV_64F, 1, 1, ksize=3)
grad_np = 2 * np.gradient(2 * np.gradient(image, axis=1), axis=0)
grad_np[:, [0, -1]] = 0
grad_np[[0, -1], :] = 0
print(np.all(grad_cv2 == grad_np))
# True

需要系数 2,因为默认情况下 np.gradient 除以 2

必须将边框设置为零,因为以下原因(我强调):

The gradient is computed using second order accurate central differences in the interior points and either first or second order accurate one-sides (forward or backwards) differences at the boundaries.

另一方面,cv2.Sobel 默认情况下使用 cv2.BORDER_REFLECT_101,因此您总是得到 0 作为边框。

大多数其他 cv2.Sobel 的情况将涉及(高斯)平滑,参见。链接文档:

The Sobel operators combine Gaussian smoothing and differentiation, so the result is more or less resistant to the noise.

不能单独使用 np.gradient 进行攻击。如果你想拥有它,你将使用 NumPy 方法重写 cv2.Sobel

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.16299-SP0
Python:        3.9.1
NumPy:         1.20.2
OpenCV:        4.5.1
----------------------------------------