2017-04-19 3 views
0

私は2D相関を計算する必要がある2D配列のセットを持っています。私は多くの異なることを試しています(Fortranでプログラミングしていても)。しかし、最も速い方法はFFTを使って計算することです。私のテストで、私はscipy.signal.fftconvolveを使用することができますし、私はboundary='fill'scipy.signal.correlate2dの出力を再現しようとしている場合、それは正常に動作しthis answerに基づいてfftconvolveで二次元相関をラップした計算

。したがって、基本的にこの

scipy.signal.fftconvolve(a, a[::-1, ::-1], mode='same') 

は、それらが2次元周期配列(あるので事は、アレイは、ラップされたモードで計算されなければならないということである

scipy.signal.correlate2d(a, a, boundary='fill', mode='same') 

(わずかなシフトを除いて)これに等しいです。すなわち、boundary='wrap')。私は私がすることはできません

scipy.signal.correlate2d(a, a, boundary='wrap', mode='same') 

の出力を再現しようとしているのであれば、または少なくとも私はそれを行う方法が表示されません。

明らかにScipyは、このトリックをした可能性があるsomething like thatを持っていたようですが、明らかに残ってしまって見つけられないので、私は思っています。(私はFFT方法を使います。 Scipyはそれをサポートしなくなったかもしれない。

とにかく、scipynumpyのFFTルーチンを使用してこの周期配列の相関を計算する方法はありますか?

+0

「a」の外観はどうですか? – kmario23

+0

@ kmario23それは私的な実験データなので、私はここで実際に共有することはできません。しかし、それはxとyで周期的な200x200配列です。 – TomCho

+1

私は現時点では良い答えがありませんが、あなたが言及した "残された"コードは[ここ](https://github.com/scipy/scipy/blob/maintenance/0.7)にあります。x/scipy/stsci/convolve/lib/Convolve.py#L144) – jakevdp

答えて

1

ラップされた相関は、FFTを使用して実装できます。

In [276]: import numpy as np 

In [277]: from scipy.signal import correlate2d 

はで動作するようにランダムな配列aを作成します:

In [278]: a = np.random.randn(200, 200) 

計算scipy.signal.correlate2dを使用して、2D相関:

In [279]: c = correlate2d(a, a, boundary='wrap', mode='same') 

今すぐ同じ結果を計算、ここでどのように証明するいくつかのコードですnumpy.fftからの2D FFT関数を使用します。 (このコードはaが正方形であると仮定し。)

In [280]: from numpy.fft import fft2, ifft2 

In [281]: fc = np.roll(ifft2(fft2(a).conj()*fft2(a)).real, (a.shape[0] - 1)//2, axis=(0,1)) 

どちらの方法も同じ結果を与えることを確認します。

In [282]: np.allclose(c, fc) 
Out[282]: True 

をそして、あなたが指摘するように、FFTを使用してはるかに高速です。

In [283]: %timeit c = correlate2d(a, a, boundary='wrap', mode='same') 
1 loop, best of 3: 3.2 s per loop 

In [284]: %timeit fc = np.roll(ifft2(fft2(a).conj()*fft2(a)).real, (a.shape[0] - 1)//2, axis=(0,1)) 
100 loops, best of 3: 3.19 ms per loop 

そして、それはfft2(a)の重複計算が含まれています。この例では、それは約1000倍高速です。もちろん、fft2(a)は一度だけ計算する必要があります。

In [285]: fta = fft2(a) 

In [286]: fc = np.roll(ifft2(fta.conj()*fta).real, (a.shape[0] - 1)//2, axis=(0,1))