Scipy实现了标准的N维卷积,因此要进行卷积的矩阵和核都是N维的。
一个快速的解决方法是给Y
添加一个额外的维度,使得Y
成为3维的:
result = signal.convolve(X, Y[..., None], 'valid')
假设在您的示例中,最后一个轴对应于图像索引,如
[width,height,image_idx]
(或
[height,width,image_idx]
)。如果情况相反,并且图像在第一个轴上进行索引(如C顺序数组中更常见),则应将
Y [..., None]
替换为
Y [None,...]
。
Y [...,None]
会向
Y
添加一个额外的轴,使其成为3维
[kernel_width,kernel_height,1]
,从而将其转换为有效的3维卷积核。
注意:这假定所有输入小批次都具有相同的
width x height
,这在CNN中是标准的。
编辑:按照@Divakar的建议进行一些计时。
测试框架设置如下:
def test(S, N, K):
""" S: image size, N: num images, K: kernel size"""
a = np.random.randn(S, S, N)
b = np.random.randn(K, K)
valid = [slice(K//2, -K//2+1), slice(K//2, -K//2+1)]
%timeit signal.convolve(a, b[..., None], 'valid')
%timeit signal.fftconvolve(a, b[..., None], 'valid')
%timeit ndimage.convolve(a, b[..., None])[valid]
以下是不同配置的测试内容:
Varying image size S
:
>>> test(100, 50, 11) # 100x100 images
1 loop, best of 3: 909 ms per loop
10 loops, best of 3: 116 ms per loop
10 loops, best of 3: 54.9 ms per loop
>>> test(1000, 50, 11) # 1000x1000 images
1 loop, best of 3: 1min 51s per loop
1 loop, best of 3: 16.5 s per loop
1 loop, best of 3: 5.66 s per loop
Varying number of images N
:
>>> test(100, 5, 11) # 5 images
10 loops, best of 3: 90.7 ms per loop
10 loops, best of 3: 26.7 ms per loop
100 loops, best of 3: 5.7 ms per loop
>>> test(100, 500, 11) # 500 images
1 loop, best of 3: 9.75 s per loop
1 loop, best of 3: 888 ms per loop
1 loop, best of 3: 727 ms per loop
Varying kernel size K
:
>>> test(100, 50, 5) # 5x5 kernels
1 loop, best of 3: 217 ms per loop
10 loops, best of 3: 100 ms per loop
100 loops, best of 3: 11.4 ms per loop
>>> test(100, 50, 31) # 31x31 kernels
1 loop, best of 3: 4.39 s per loop
1 loop, best of 3: 220 ms per loop
1 loop, best of 3: 560 ms per loop
因此,简而言之,
ndimage.convolve
总是更快的,除非卷积核的大小非常大(例如,在最后一个测试中,
K = 31
)。
ndimage.filters.convolve(X,Y[...,None])
,也许需要进行一些切片操作? - Divakarndimage,filters.convolve
应该会更慢(因为它在空间域中进行卷积,而signal.convolve
在傅里叶域中进行卷积)。ndimage
滤波器的优点是支持不同的边界条件(与傅里叶不同,我认为根据定义等价于用 0 填充图像)。我会尽快进行计时! - Imanol Luengondimage.convolve
通常更快。我记得在另一个线程中也有过类似的对话哈哈。 - Imanol Luengouniform_filter
而不是signal.convolve
。虽然由于内核的可分离性,uniform_filter
更快,但上述结果似乎证实了我们在那个线程中得出的结论:对于大内核大小,傅里叶变换(fftconvolve)>空间卷积,否则空间卷积>傅里叶变换。 - Imanol Luengo