Вычислить функцию взаимной корреляции?

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

Ответ 1

Для кросс-корреляции массивов 1d используйте numpy.correlate.

Для 2d массивов используйте scipy.signal.correlate2d.

Существует также scipy.stsci.convolve.correlate2d.

Существует также matplotlib.pyplot.xcorr, основанный на numpy.correlate.

См. этот пост в списке рассылки SciPy для некоторых ссылок на различные реализации.

Изменить: @user333700 добавил ссылку на билет SciPy для этой проблемы в комментарии.

Ответ 2

Если вы ищете быструю нормализованную взаимную корреляцию в одном или двух измерениях Я бы порекомендовал библиотеку openCV (см. http://opencv.willowgarage.com/wiki/ http://opencv.org/). Кодекс взаимной корреляции, поддерживаемый этой группой, является самым быстрым, который вы найдете, и он будет нормализован (результаты между -1 и 1).

Хотя это С++-библиотека, код поддерживается с помощью 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)

Только для одномерной кросс-корреляции создайте двухмерный массив с формой, равной (N, 1). Хотя для преобразования в формат openCV есть некоторый дополнительный код, ускорение по scipy довольно впечатляет.

Ответ 3

Я только что закончил писать собственную оптимизированную реализацию нормированной кросс-корреляции для N-мерных массивов. Вы можете получить его от здесь.

Он будет вычислять кросс-корреляцию либо напрямую, используя scipy.ndimage.correlate, либо в частотной области, используя scipy.fftpack.fftn/ifftn в зависимости от того, что будет быстрее.