scipy和numpy sobel梯度计算之间的区别

时间:2019-02-14 08:23:58

标签: python numpy scipy

设置

我目前正在尝试使用sobel滤波器计算图像梯度。 最初,我通过scipy.ndimage.sobel函数

sx = ndimage.sobel(im, axis=0,mode="constant")
sy = ndimage.sobel(im, axis=1,mode="constant")
sobel = np.hypot(sx,sy)
sobel *= 255 / np.max(sobel)

但是,这仅将(3x3)sobel滤镜应用于我的图像,但是我想尝试更大的滤镜。因此,我尝试使用numpyscipy.signal计算图像梯度。首先,我再次尝试了(3x3)过滤器。

filter_x = np.array([[-1,0,1],[-2,0,2],[-1,0,1]], dtype=np.float)
filter_y = np.array([[1,2,1], [0,0,0], [-1,-2,-1]], dtype = np.float)
sx = signal.convolve2d(im,filter_x,mode="same",boundary="symm", fillvalue=0)
sy = signal.convolve2d(im,filter_y,mode="same",boundary="symm", fillvalue=0)
sobel = np.hypot(sx,sy)
sobel *= 255 / np.max(sobel)

作为this帖子中的建议。

问题

不幸的是,这两种方法都导致完全不同的结果,这在this问题中已经提到。 因此,我进行了更深入的研究,发现scipy.ndimage.sobel使用correlate1d函数而不是convolve2d或类似的(source code)。不幸的是,无法查看correlate1d函数的源代码,因为它的功能隐藏在我的conda环境的site-packages文件夹中已经编译的_nd_image.pyd文件中。所以这是我的问题:

问题

有人清楚地知道correlate1d到底在计算什么,它与convolve2d有什么可比性?

修改

正如在Florian Drawitsch的回答中已经提到的那样,人们应该能够用相关性代替卷积。但是话又说回来,这些不同的结果如何出现?!

1 个答案:

答案 0 :(得分:3)

从方法名correlate1dconvolve2d来看,我强烈怀疑前者计算相关性,而后者计算卷积。有什么区别?

通常来说,信号f与内核g的卷积涉及在操作f*g(-t)之前翻转内核:f

相比之下,信号g与内核f*g(t)的相关性无需翻转内核即可完成:import numpy as np from scipy import signal from PIL import Image from matplotlib import pyplot as plt img = Image.open('lena.png') plt.imshow(img)

因此,与使用相关性的结果相比,使用卷积应用定向边缘检测内核(例如sobel内核)应该会导致边缘倒置。让我们在代码中对此进行测试:

g = np.asarray([[-1, 0, 1],
                [-2, 0, 2],
                [-1, 0, 1]])

enter image description here

首先,让我们定义一个sobel边缘检测内核:

signal.convolve2d

现在让我们首先使用sicpy的img_convolved = signal.convolve2d(img, g) plt.imshow(img_convolved, cmap='gray')

将图像与内核进行卷积
plt.imshow(img_convolved[100:150,100:150], cmap='gray')

enter image description here

...并放大边缘:

signal.correlate2d

enter image description here

现在,让我们使用sicpy的img_correlated = signal.correlate2d(img, g) plt.imshow(img_correlated, cmap='gray')

将图像与内核相关联
plt.imshow(img_correlated[100:150,100:150], cmap='gray')

enter image description here

...并放大边缘:

img_convolved_flipped = signal.convolve2d(img, np.fliplr(g))
plt.imshow(img_convolved, cmap='gray')

enter image description here

最后,让我们将相关结果与如果使用翻转内核进行卷积会发生的情况进行比较:

plt.imshow(img_convolved_flipped[100:150,100:150], cmap='gray')

enter image description here

...并放大边缘:

signal.correlate2d(img, g)

enter image description here

因此,scipy的signal.convolve2d(img, np.fliplr(g))等效于f

编辑(对2D代码示例进行说明):

请注意,在2D情况下,信号g与内核f*g(-t,-u)的卷积涉及围绕两个基本轴np.flipud(np.fliplr(g))翻转内核。

因此,在我的代码中,我实际上应该将过滤器翻转两次: powershell -command "Start-BitsTransfer -Source https://prod-corp.net/public/Folder.zip -Destination C:\temp" powershell -command "Expand-Archive -Path C:\temp\Folder.zip -DestinationPath C:\temp -Force" 。我已经省略了这一点,因为对于垂直对称的sobel滤波器不是必需的,但是请记住,这是一种特殊情况。