web-dev-qa-db-fra.com

Calculer l'autocorrélation à l'aide de FFT dans Matlab

J'ai lu quelques explications sur la façon dont l'autocorrélation peut être calculée plus efficacement en utilisant le fft d'un signal, en multipliant la partie réelle par le conjugué complexe (domaine de Fourier), puis en utilisant le fft inverse, mais j'ai du mal à le réaliser dans Matlab car à un niveau détaillé.

22
skj

Tout comme vous l'avez dit, prenez le fft et multipliez point par point son conjugué complexe, puis utilisez l'inverse fft (ou dans le cas de la corrélation croisée de deux signaux: Corr(x,y) <=> FFT(x)FFT(y)*)

x = Rand(100,1);
len = length(x);

%# autocorrelation
nfft = 2^nextpow2(2*len-1);
r = ifft( fft(x,nfft) .* conj(fft(x,nfft)) );

%# rearrange and keep values corresponding to lags: -(len-1):+(len-1)
r = [r(end-len+2:end) ; r(1:len)];

%# compare with MATLAB's XCORR output
all( (xcorr(x)-r) < 1e-10 )

En fait, si vous regardez le code de xcorr.m, c'est exactement ce qu'il fait (seulement il doit gérer tous les cas de remplissage, de normalisation, d'entrée vectorielle/matricielle, etc ...)

30
Amro

Par le théorème de Wiener – Khinchin , la densité spectrale de puissance (PSD) d'une fonction est la transformée de Fourier de l'autocorrélation. Pour les signaux déterministes, la PSD est simplement la grandeur au carré de la transformée de Fourier. Voir aussi le théorème de convolution .

En ce qui concerne les transformées de Fourier discrètes (c'est-à-dire en utilisant des FFT), vous obtenez en fait l'autocorrélation cyclique. Afin d'obtenir une autocorrélation (linéaire) correcte, vous devez mettre à zéro les données d'origine à deux fois sa longueur d'origine avant de prendre la transformée de Fourier. Donc quelque chose comme:

x = [ ... ];
x_pad = [x zeros(size(x))];
X     = fft(x_pad);
X_psd = abs(X).^2;
r_xx = ifft(X_psd);
28