基于FFT的Python二维卷积与相关性
有没有基于快速傅里叶变换(FFT)的二维交叉相关或卷积函数,内置在scipy(或其他流行的库)中?
有一些这样的函数:
scipy.signal.correlate2d
- “直接使用convolveND
的方法在处理大数据时会很慢。”scipy.ndimage.correlate
- “这个数组会和给定的核进行精确计算的相关(也就是说,不使用FFT)。”scipy.fftpack.convolve.convolve
,我不是很明白,但感觉好像不太对。
numarray曾经有一个correlate2d()
函数,带有fft=True
的选项,但我猜numarray已经合并到numpy里了,我找不到这个函数是否被包含在内。
6 个回答
5
我觉得你想要的是scipy.stsci这个包:
http://docs.scipy.org/doc/scipy/reference/stsci.html
In [30]: scipy.__version__
Out[30]: '0.7.0'
In [31]: from scipy.stsci.convolve import convolve2d, correlate2d
8
你可以看看scipy库里的几个函数,比如fftconvolve、convolve和correlate。还有一个叫signal.correlate2d的函数,不过它返回的数组好像是偏移的,而不是居中的。
25
我发现了 scipy.signal.fftconvolve
,正如 magnus 也提到过的,但当时没意识到它是支持多维的。因为这个函数是内置的,并且能产生正确的结果,所以看起来是个理想的解决方案。
来自 二维卷积的例子:
In [1]: a = asarray([[ 1, 2, 3],
...: [ 4, 5, 6],
...: [ 7, 8, 9]])
In [2]: b = asarray([[-1,-2,-1],
...: [ 0, 0, 0],
...: [ 1, 2, 1]])
In [3]: scipy.signal.fftconvolve(a, b, mode = 'same')
Out[3]:
array([[-13., -20., -17.],
[-18., -24., -18.],
[ 13., 20., 17.]])
没错!而 STSCI 版本则需要额外的工作来处理边界问题,对吧?
In [4]: stsci.convolve2d(a, b, fft = True)
Out[4]:
array([[-12., -12., -12.],
[-24., -24., -24.],
[-12., -12., -12.]])
(STSCI 方法还需要编译,我尝试过但没成功(我只是把非 Python 的部分注释掉了),还有一些 bug,比如 这个,以及输入需要修改(比如 [1, 2] 变成 [[1, 2]])等等。所以我把我之前认可的答案改成了内置的 fftconvolve()
函数。)
当然,相关性和卷积是一样的,只不过一个输入是反向的:
In [5]: a
Out[5]:
array([[3, 0, 0],
[2, 0, 0],
[1, 0, 0]])
In [6]: b
Out[6]:
array([[3, 2, 1],
[0, 0, 0],
[0, 0, 0]])
In [7]: scipy.signal.fftconvolve(a, b[::-1, ::-1])
Out[7]:
array([[ 0., -0., 0., 0., 0.],
[ 0., -0., 0., 0., 0.],
[ 3., 6., 9., 0., 0.],
[ 2., 4., 6., 0., 0.],
[ 1., 2., 3., 0., 0.]])
In [8]: scipy.signal.correlate2d(a, b)
Out[8]:
array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[3, 6, 9, 0, 0],
[2, 4, 6, 0, 0],
[1, 2, 3, 0, 0]])
而且 最新的版本通过使用二的幂的大小在内部加快了速度(然后我通过 对真实输入使用真实 FFT 和 使用 5 平滑长度而不是 2 的幂 进一步加快了速度 :D)。