2017-09-13 39 views
0

圆形FFT卷积我需要的需要在Python

scipy.signal.convolve2d(data, filter, boundary="wrap", mode="same") 

更快的模拟你能不能指点我如何取代它?

P.S. scipy.signal.fftconvolve速度够快,但它没有boundary选项,我无法使其在循环卷积模式下工作。

+0

我认为没有边界选项的原因是因为FFT不能像那样工作。而“循环”卷积究竟是什么意思?编辑:没关系,我在[Wikipedia](https://en.wikipedia.org/wiki/Circular_convolution)上找到了一个定义。 –

回答

2

如果计算如下:

from scipy.fftpack import fft2, ifft2 

f2 = ifft2(fft2(data, shape=data.shape) * fft2(filter, shape=data.shape)).real 

然后f2包含相同的值作为convolve2d(data, filt, boundary='wrap', mode='same'),但值被移位(“滚动”,在numpy的术语)中的每个轴。 (这是convolution theorem的一个应用程序。)

这里的一个短函数滚动的结果向得到相同的结果convolve2d函数调用:

def fftconvolve2d(x, y): 
    # This assumes y is "smaller" than x. 
    f2 = ifft2(fft2(x, shape=x.shape) * fft2(y, shape=x.shape)).real 
    f2 = np.roll(f2, (-((y.shape[0] - 1)//2), -((y.shape[1] - 1)//2)), axis=(0, 1)) 
    return f2 

例如,

In [91]: data = np.random.rand(256, 256) 

In [92]: filt = np.random.rand(16, 16) 

In [93]: c2d = convolve2d(data, filt, boundary='wrap', mode='same') 

In [94]: f2 = fftconvolve2d(data, filt) 

验证结果是否相同:

In [95]: np.allclose(c2d, f2) 
Out[95]: True 

Check性能:

In [96]: %timeit c2d = convolve2d(data, filt, boundary='wrap', mode='same') 
44.9 ms ± 77.3 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) 

In [97]: %timeit f2 = fftconvolve2d(data, filt) 
5.23 ms ± 11.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 

的FFT版本更快(但请注意,我选择的data尺寸是2的幂)。

+0

谢谢同志!我认为就是这样! ^ __ ^ – Felix