Calcul efficace de l'autocorrélation à l'aide des FFT


12

J'essaie de calculer une autocorrélation sur une plate-forme où la seule primitive accélérée dont je dispose est la (I) FFT. J'ai un problème cependant.

Je l'ai prototypé dans MATLAB . Je suis cependant légèrement confus. J'ai supposé que cela fonctionne simplement comme suit (c'est de mémoire donc excuses si je me trompe un peu).

 autocorr = ifft( complex( abs( fft( inputData ) ), 0 ) )

Cependant, j'obtiens un résultat différent de celui obtenu en utilisant la xcorrfonction. Maintenant, je m'attends à ne pas obtenir le côté gauche de la corrélation automatique (car c'est un reflet du côté droit et donc pas nécessaire de toute façon). Cependant, le problème est que mon côté droit semble être lui-même réfléchi autour de la mi-course. Ce qui signifie effectivement que j'obtiens environ la moitié de la quantité de données que j'attends.

Je suis donc sûr que je dois faire quelque chose de très simple, mais je n'arrive pas à comprendre quoi.


1
Faites attention. À moins que les données ne soient déterministes, nous ne pouvons généralement estimer que la séquence d'autocorrélation. Il existe deux versions courantes d'estimations d'autocorrélation: biaisée et non biaisée. Des résultats non biaisés donnent des estimations d'autocorrélation statistiquement non biaisées. Cependant, la variance peut être très importante pour des décalages d'ordre élevé, ce qui peut poser des problèmes si l'estimation d'autocorrélation est utilisée dans les inversions matricielles par exemple. Les échantillons biaisés présentent un biais statistique mais avec moins de variance (et d'erreur quadratique moyenne). Les deux sont statistiquement cohérents. Vous avez une estimation biaisée non normalisée ci-dessus.
Bryan

Réponses:


16

pichenettes a raison, bien sûr. La FFT implémente une convolution circulaire tandis que le xcorr () est basé sur une convolution linéaire. De plus, vous devez également ajuster la valeur absolue dans le domaine fréquentiel. Voici un extrait de code qui gère tout le remplissage, le décalage et la troncature zéro.

%% Cross correlation through a FFT
n = 1024;
x = randn(n,1);
% cross correlation reference
xref = xcorr(x,x);

%FFT method based on zero padding
fx = fft([x; zeros(n,1)]); % zero pad and FFT
x2 = ifft(fx.*conj(fx)); % abs()^2 and IFFT
% circulate to get the peak in the middle and drop one
% excess zero to get to 2*n-1 samples
x2 = [x2(n+2:end); x2(1:n)];
% calculate the error
d = x2-xref; % difference, this is actually zero
fprintf('Max error = %6.2f\n',max(abs(d)));

Wow qui a fonctionné une belle. Une version C droite (Single threaded, no SIMD) de mon pitch tracker a fonctionné en 0,8 seconde en utilisant la méthode ci-dessus par opposition à une version basée sur une primitive de performances Intel qui a fonctionné en 0,4 seconde. C'est incroyable! Merci
Goz


3

N2N1[(N1),N1]0

2N12N12N12N1

N2N1N

N1N2N102N12N1

En bref: vous auriez dû le faire (pour être adapté à votre langage de programmation):

autocorr = ifft( complex( abs(fft(inputData, n=2*N-1))**2, 0 ) )

Ou dans MATLAB:

autocorr = ifft(abs(fft(inputData, 2*N-1)).^2)

0

La principale raison pour laquelle la sortie souhaitée de la fonction xcorr n'est pas similaire à celle de l'application des fonctions FFT et IFFT est que, tout en appliquant ces fonctions aux signaux, le résultat final est alambiqué de façon circulaire .

La principale différence entre la convolution linéaire et la convolution circulaire se trouve dans la convolution linéaire et circulaire .

Le problème peut être résolu en initialisant initialement le signal à zéro et en tronquant la sortie finale de l' IFFT .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.