计算互相关函数?

时间:2011-08-09 04:46:17

标签: python r statistics numpy scipy

R中,我使用ccfacf来计算成对互相关函数,以便我可以找出哪个班次给了我最大值。从它的外观来看,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)

4 个答案:

答案 0 :(得分:38)

要对1d数组进行交叉关联,请使用numpy.correlate

对于2D阵列,请使用scipy.signal.correlate2d

还有scipy.stsci.convolve.correlate2d

还有matplotlib.pyplot.xcorr基于numpy.correlate。

有关不同实现的链接,请参阅this post on the SciPy mailing list

修改:@ user333700在评论中添加了SciPy ticket for this issue的链接。

答案 1 :(得分:13)

如果您正在寻找一维或二维的快速标准化互相关 我建议使用openCV库(参见 http://opencv.willowgarage.com/wiki/ http://opencv.org/)。该组维护的互相关代码是您发现的最快,它将被标准化(结果在-1和1之间)。

虽然这是一个C ++库,但代码是使用CMake维护的,并且具有python绑定,因此可以方便地访问互相关函数。 OpenCV也很适合numpy。如果我想从numpy数组开始计算二维互相关,我可以按如下方式进行。

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-D互相关,创建形状等于(N,1)的2-D阵列。虽然转换为openCV格式需要一些额外的代码,但是scipy的加速速度令人印象深刻。

答案 2 :(得分:11)

我刚刚为N维数组编写了自己的规范化互相关优化实现。您可以从 here 获取。

它将使用scipy.ndimage.correlate直接计算互相关,或使用scipy.fftpack.fftn / ifftn在频域中计算互相关,具体取决于哪个最快。

答案 3 :(得分:2)

对于一维数组,usernamenumpy.correlate快,在不同大小的情况下,我看到使用scipy.signal.correlate可获得一致的5倍性能增益。当两个阵列的大小相似(亮线连接对角线)时,性能差异会更加明显(50x +)。

numpy.correlate

enter image description here

默认情况下,scipy.signal.correlate通过填充计算一些额外的数字,这可能解释了性能差异。

# 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))