在与@Divakar 讨论之后,在下面找到 scipy 中存在的不同卷积方法的比较:
import numpy as np
from scipy import signal, ndimage
def conv2(A, size):
return signal.convolve2d(A, np.ones((size, size)), mode='same') / float(size**2)
def fftconv(A, size):
return signal.fftconvolve(A, np.ones((size, size)), mode='same') / float(size**2)
def uniform(A, size):
return ndimage.uniform_filter(A, size, mode='constant')
所有 3 种方法都返回完全相同的值。但是,请注意,它uniform_filter
有一个参数mode='constant'
,它指示滤波器的边界条件,并且与constant == 0
强制执行傅里叶域(在其他 2 种方法中)的边界条件相同。对于不同的用例,您可以更改边界条件。
现在一些测试矩阵:
A = np.random.randn(1000, 1000)
还有一些时间:
%timeit conv2(A, 3) # 33.8 ms per loop
%timeit fftconv(A, 3) # 84.1 ms per loop
%timeit uniform(A, 3) # 17.1 ms per loop
%timeit conv2(A, 5) # 68.7 ms per loop
%timeit fftconv(A, 5) # 92.8 ms per loop
%timeit uniform(A, 5) # 17.1 ms per loop
%timeit conv2(A, 10) # 210 ms per loop
%timeit fftconv(A, 10) # 86 ms per loop
%timeit uniform(A, 10) # 16.4 ms per loop
%timeit conv2(A, 30) # 1.75 s per loop
%timeit fftconv(A, 30) # 102 ms per loop
%timeit uniform(A, 30) # 16.5 ms per loop
所以简而言之,uniform_filter
似乎更快,这是因为卷积在两个 1D 卷积中是可分离的(类似于gaussian_filter也是可分离的)。
其他具有不同内核的不可分离过滤器更有可能使用signal
模块(@Divakar's 中的那个)解决方案更快。
对于不同的内核大小,两者的速度保持不变,而fftconvolve
速度会uniform_filter
稍微慢convolve2d
一些。