Calcul de la fonction de corrélation croisée?

dans R , j'utilise ccf ou acf pour calculer la fonction de corrélation croisée par paire afin que je puisse trouver quel décalage me donne la valeur maximale. A première vue, R me donne une séquence normalisée de valeurs. Y a-t-il quelque chose de similaire dans le scipy de Python ou suis-je censé le faire en utilisant le module fft ? Actuellement, je le fais comme suit:

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)
25
demandé sur agf 2011-08-09 08:46:17

4 réponses

De cross-corrélation tableaux 1d utiliser numpy.corréler .

pour les matrices 2d, utilisez scipy.signal.correlate2d .

il y a aussi scipy.stsci.de convolution.correlate2d .

il y a aussi matplotlib.pyplot.xcorr qui est basé sur numpy.corrélation.

Voir ce post sur le SciPy liste de diffusion pour certains liens vers différentes implémentations.

éditer: @user333700 a ajouté un lien vers le SciPy ticket pour ce numéro dans un commentaire.

37
répondu agf 2018-02-12 01:35:51

si vous recherchez une corrélation croisée normalisée rapide en une ou deux dimensions Je recommande la bibliothèque openCV (voir http://opencv.willowgarage.com/wiki/ http://opencv.org / ). Le code de corrélation croisée maintenu par ce groupe est le plus rapide que vous trouverez, et il sera normalisé (résultats entre -1 et 1).

alors qu'il s'agit D'une bibliothèque C++ le code est maintenu avec CMake et a des fixations python de sorte que l'accès aux fonctions de corrélation croisée est pratique. OpenCV joue aussi bien avec numpy. Si je voulais calculer une corrélation croisée 2-D à partir de tableaux numpy je pourrais le faire comme suit.

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)

pour une simple corrélation croisée 1-D, créer un tableau 2-D de forme égale à (N, 1 ). Bien qu'il y ait un peu de code supplémentaire impliqué pour passer à un format openCV la vitesse sur scipy est assez impressionnante.

12
répondu ncRubert 2014-01-21 19:33:03

je viens de terminer l'écriture de ma propre mise en œuvre optimisée de la corrélation normalisée pour les matrices n-dimensionnelles. Vous pouvez l'obtenir de ici .

il calculera la corrélation croisée soit directement, en utilisant scipy.ndimage.correlate , soit dans le domaine de fréquence, en utilisant scipy.fftpack.fftn / ifftn selon celui qui sera le plus rapide.

11
répondu ali_m 2012-09-03 23:05:03

pour un tableau 1D, numpy.correlate est plus rapide que scipy.signal.correlate , sous différentes tailles, je vois un gain de performance 5X constant en utilisant numpy.correlate . Lorsque deux tableaux sont de taille similaire (la ligne brillante reliant la diagonale), la différence de performance est encore plus remarquable (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

par défaut, scipy.signal.corrélation calcule quelques chiffres supplémentaires par remplissage et qui pourrait expliqué la différence de performances.

>> 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]
1
répondu B.Mr.W. 2018-08-18 15:24:11