web-dev-qa-db-ja.com

相互相関関数を計算していますか?

Rでは、ccfまたはacfを使用してペアワイズ相互相関関数を計算しているので、どのシフトが最大値を与えるかがわかります。その外観から、Rは値の正規化されたシーケンスを提供します。 Pythonのscipyに似たようなものがありますか、またはfftモジュールを使用してそれを行うことになっていますか?現在、私は次のようにしています:

xcorr = lambda x,y : irfft(rfft(x)*rfft(y[::-1]))
x = numpy.array([0,0,1,1])
y = numpy.array([1,1,0,0])
print xcorr(x,y)
30
Legend

1d配列を相互相関させるには、 numpy.correlate を使用します。

2次元配列の場合、 scipy.signal.correlate2d を使用します。

scipy.stsci.convolve.correlate2d もあります。

matplotlib.pyplot.xcorr もあり、これはnumpy.correlateに基づいています。

さまざまな実装へのリンクについては、 SciPyメーリングリストのこの投稿 を参照してください。

編集:@ user333700は、コメントに この問題のSciPyチケット へのリンクを追加しました。

41
agf

1次元または2次元の高速で正規化された相互相関を探しているなら、openCVライブラリをお勧めします( http://opencv.willowgarage.com/wiki/ http://opencv.org/ )。このグループが保持する相互相関コードは、最も高速であり、正規化されます(結果は-1〜1)。

これはC++ライブラリですが、コードはCMakeで管理され、pythonバインディングがあるため、相互相関関数へのアクセスが便利です。OpenCVもnumpyでうまく再生されます。 numpy配列から始まる-D相互相関私はそれを次のように行うことができました。

import numpy
import cv

#Create a random template and place it in a larger image
templateNp = numpy.random.random( (100,100) )
image = numpy.random.random( (400,400) )
image[:100, :100] = templateNp

#create a numpy array for storing result
resultNp = numpy.zeros( (301, 301) )

#convert from numpy format to openCV format
templateCv = cv.fromarray(numpy.float32(template))
imageCv = cv.fromarray(numpy.float32(image))
resultCv =  cv.fromarray(numpy.float32(resultNp))

#perform cross correlation
cv.MatchTemplate(templateCv, imageCv, resultCv, cv.CV_TM_CCORR_NORMED)

#convert result back to numpy array
resultNp = np.asarray(resultCv)

1次元相互相関だけの場合、形状が(N、1)に等しい2次元配列を作成します。 openCV形式に変換するためのコードがいくつかありますが、scipyの高速化は非常に印象的です。

14
ncRubert

N次元配列の正規化相互相関の最適化された実装を作成しました。から入手できます ここ

scipy.ndimage.correlateを使用して直接相関を計算するか、scipy.fftpack.fftn/ifftnを使用して周波数領域で相互相関を計算します。

11
ali_m

1D配列の場合、numpy.correlatescipy.signal.correlateよりも高速ですが、サイズが異なると、numpy.correlateを使用すると、一貫した5倍のパフォーマンス向上が見られます。 2つのアレイが同じサイズ(対角線を結ぶ明るい線)である場合、パフォーマンスの違いはさらに顕著です(50x +)。

# a simple benchmark
res = []
for x in range(1, 1000):
    list_x = []
    for y in range(1, 1000): 

        # generate different sizes of series to compare
        l1 = np.random.choice(range(1, 100), size=x)
        l2 = np.random.choice(range(1, 100), size=y)

        time_start = datetime.now()
        np.correlate(a=l1, v=l2)
        t_np = datetime.now() - time_start

        time_start = datetime.now()
        scipy.signal.correlate(in1=l1, in2=l2)
        t_scipy = datetime.now() - time_start

        list_x.append(t_scipy / t_np)
    res.append(list_x)
plt.imshow(np.matrix(res))

enter image description here

デフォルトとして、scipy.signal.correlateはパディングによっていくつかの余分な数値を計算しますが、これがパフォーマンスの違いを説明する可能性があります。

>> l1 = [1,2,3,2,1,2,3]
>> l2 = [1,2,3]
>> print(numpy.correlate(a=l1, v=l2))
>> print(scipy.signal.correlate(in1=l1, in2=l2))

[14 14 10 10 14]
[ 3  8 14 14 10 10 14  8  3]  # the first 3 is [0,0,1]dot[1,2,3]
2
B.Mr.W.