需要Python中的循环FFT卷积

Fel*_*lix 2 python convolution scipy

我需要更快的模拟

scipy.signal.convolve2d(data, filter, boundary="wrap", mode="same")
Run Code Online (Sandbox Code Playgroud)

你不能建议我如何更换它吗?

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

War*_*ser 5

如果您计算以下内容:

\n\n
from scipy.fftpack import fft2, ifft2\n\nf2 = ifft2(fft2(data, shape=data.shape) * fft2(filter, shape=data.shape)).real\n
Run Code Online (Sandbox Code Playgroud)\n\n

thenf2包含与 相同的值convolve2d(data, filt, boundary=\'wrap\', mode=\'same\'),但这些值在每个轴上移动(用 numpy 术语来说是“滚动”)。(这是卷积定理的一个应用。)

\n\n

这是一个简短的函数,它将结果滚动到与convolve2d函数调用相同的结果:

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

例如,

\n\n
In [91]: data = np.random.rand(256, 256)\n\nIn [92]: filt = np.random.rand(16, 16)\n\nIn [93]: c2d = convolve2d(data, filt, boundary=\'wrap\', mode=\'same\')\n\nIn [94]: f2 = fftconvolve2d(data, filt)\n
Run Code Online (Sandbox Code Playgroud)\n\n

验证结果是否相同:

\n\n
In [95]: np.allclose(c2d, f2)\nOut[95]: True\n
Run Code Online (Sandbox Code Playgroud)\n\n

检查性能:

\n\n
In [96]: %timeit c2d = convolve2d(data, filt, boundary=\'wrap\', mode=\'same\')\n44.9 ms \xc2\xb1 77.3 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 10 loops each)\n\nIn [97]: %timeit f2 = fftconvolve2d(data, filt)\n5.23 ms \xc2\xb1 11.2 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 100 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n\n

FFT 版本要快得多(但请注意,我选择 的维度data为 2 的幂)。

\n