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)
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.
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.
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.
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))
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]