Sei sulla pagina 1di 16

9.

FAST FOURIER TRANSFORM (FFT)


Trasformata di Fourier continua: f()= f(t) exp(-2 i t) dt Consideriamo ora una funzione discreta fk=f(tk) con tk=k*, k=0,,N-1. La trasformata di Fourier discreta (DFT) definita da: Fn= k=0N-1 fk exp(- 2 i n k/N) La FFT riduce il numero di calcoli necessari per N punti da 2 N^2 a 2 N log(N). La funzione fft fornisce la DFT y di un vettore input x usando lalgoritmo FFT: y = fft(x); La lunghezza della trasformata pu essere specificata da un secondo argomento opzionale: y = fft(x,n);

La FFT consente di stimare in maniera efficace le frequenze fondamentali a partire da un insieme discreto di dati assegnati ad intervalli fissati. Quantit rilevanti nella FFT sono indicate nella tabella.
Quantit x m = length(x) fs dt = 1/fs t = (0:m-1)/fs y = fft(x,n) abs(y) (abs(y).^2)/n fs/n f = (0:n-1)*(fs/n) fs/2 Descrizione Sampled data Window length (number of samples) Samples/unit time Time increment per sample Time range for data Discrete Fourier transform (DFT) Amplitude of the DFT Power of the DFT Frequency increment Frequency range Nyquist frequency

Per esempio consideriamo i dati x con due frequenze di diversa ampiezza e un rumore: fs = 100; % Sample frequency (Hz) t = 0:1/fs:10-1/fs; % 10 sec sample x = (1.3)*sin(2*pi*15*t) ... % 15 Hz component + (1.7)*sin(2*pi*40*(t-2)) ... % 40 Hz component + (2.5)*randn(size(t)); % Gaussian noise; Usare fft per calcolare la DFT y: m = length(x); % Window length n = pow2(nextpow2(m)); % Transform length y = fft(x,n); % DFT f = (0:n-1)*(fs/n); % Frequency range power = y.*conj(y)/n; % Power of the DFT nextpow2 trova lesponente della potenza di 2 della window length (ceil(log2(m))) pow2 calcola la potenza.

Per visualizzare la DFT si usano i plot di abs(y), abs(y).^2, and log(abs(y)) . Un plot della potenza versus frequenza si chiama periodogramma: plot(f,power) xlabel('Frequency (Hz)') ylabel('Power') title('{\bf Periodogram}')
In molte applicazioni si usa centrare il periodogramma in 0. La funzione fftshift arrangia loutput di fft per produrre un periodogramma centrato in 0: y0 = fftshift(y); % Rearrange y values f0 = (-n/2:n/2-1)*(fs/n); % 0-centered frequency range power0 = y0.*conj(y0)/n; % 0-centered power plot(f0,power0) title('{\bf 0-Centered Periodogram}')

FFT per loscillatore armonico


Consideriamo lequazione delloscillatore armonico di una pallina di massa m collegata ad una molla di costante elastica k: y + 2 y = 0 con 2 = k/m e condizioni iniziali y(0)=2/16, y(0)=0. La soluzione esatta : y = y(0) cos( t) . Calcoliamo k a partire da una misurazione di y, che assumiamo sia affetta da rumore; le misure sono effettuate nellintervallo (con frequenza 2^7=128 Hz): >> tspan=[0:2^(-7):128-2^(-7)];

Costruiamo il segnale yvn sovrapponendo ad un segnale con un contenuto in frequenza di 50 Hz, che chiamiamo yv, del rumore casuale a media nulla (prendiamo 27 intervalli):
>> omega=2*pi*50; >> y0=2*pi/16; >> N=length(tspan); >> f=128/N*(0:N/2-1); >> yv=y0*cos(omega*tspan); >> yvn=yv+4*randn(size(tspan)); Analizziamo il segnale misurato nel dominio delle frequenze, calcolando la FFT di yvn.

In generale, se y ha N componenti, il comando fft(y) calcola i coefficienti dello sviluppo di Fourier secondo la relazione:
F(k) = j=1N y(j) N (j-1)(k-1) , dove N = e-2/N .

>> YVN=fft(yvn);
calcoliamo la densit di energia spettrale, definita come: P= k=1N (F(k) * F(k)c) / N ; dove F(k)c indica il coniugato di F(k): >> PVN=YVN.*conj(YVN)/N; >> plot(f,PVN(1:N/2)) (spettro della densit di energia del segnale)

Valutiamo con max il valore della frequenza dove si registra il massimo della densit di energia spettrale: >> [y,j]=max(PVN); >> f(j) ans= 50
ovvero il massimo di energia viene registrato per una frequenza pari a 50 Hz.

EXAMPLE from MATHWORKS

A common use of Fourier transforms is to find the frequency components of a signal buried in a noisy time domain signal. Consider data sampled at 1000 Hz. Form a signal containing a 50 Hz sinusoid of amplitude 0.7 and 120 Hz sinusoid of amplitude 1 and corrupt it with some zeromean random noise.

Fs = 1000; % Sampling frequency T = 1/Fs; % Sample time L = 1000; % Length of signal t = (0:L-1)*T; % Time vector % Sum of a 50 Hz sinusoid and a 120 Hz sinusoid x = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t); y = x + 2*randn(size(t)); % Sinusoids plus noise plot(Fs*t(1:50),y(1:50)) title('Signal Corrupted with Zero-Mean Random Noise') xlabel('time (milliseconds)')

It is difficult to identify the frequency components by looking at the original signal. Converting to the frequency domain, the discrete Fourier transform of the noisy signal y is found by taking the fast Fourier transform (FFT):

NFFT = 2^nextpow2(L); % Next power of 2 from length of y Y = fft(y,NFFT)/L; f = Fs/2*linspace(0,1,NFFT/2+1); % Plot single-sided amplitude spectrum. plot(f,2*abs(Y(1:NFFT/2+1))) title('Single-Sided Amplitude Spectrum of y(t)') xlabel('Frequency (Hz)') ylabel('|Y(f)|')
The main reason the amplitudes are not exactly at 0.7 and 1 is because of the noise. Several executions of this code (including recomputation of y) will produce different approximations to 0.7 and 1. The other reason is that you have a finite length signal. Increasing L from 1000 to 10000 in the example above will produce much better approximations on average.

Using FFT (sunspot.dat) This demonstration uses the FFT function to analyze the variations in sunspot activity over the last 300 years. Sunspot activity is cyclical, reaching a maximum about every 11 years. Let's confirm that. Here is a plot of a quantity called the Zurich sunspot relative number, which measures both number and size of sunspots. Astronomers have tabulated this number for almost 300 years. load sunspot.dat year=sunspot(:,1); relNums=sunspot(:,2); plot(year,relNums) title('Sunspot Data')

Here is a closer look at the first 50 years. plot(year(1:50),relNums(1:50),'b.-'); The first component of Y, Y(1), is simply the sum of the data, and can be removed. Y = fft(relNums); Y(1)=[];
A graph of the distribution of the Fourier coefficients (given by Y) in the complex plane is pretty, but difficult to interpret. We need a more useful way of examining the data in Y. plot(Y,'ro') title('Fourier Coefficients in the Complex Plane'); xlabel('Real Axis'); ylabel('Imaginary Axis');

The complex magnitude squared of Y is called the power, and a plot of power versus frequency is a "periodogram". n=length(Y); power = abs(Y(1:floor(n/2))).^2; nyquist = 1/2; freq = (1:n/2)/(n/2)*nyquist; plot(freq,power) xlabel('cycles/year') title('Periodogram')

The scale in cycles/year is somewhat inconvenient. We can plot in years/cycle and estimate the length of one cycle. plot(freq(1:40),power(1:40)) xlabel('cycles/year') Now we plot power versus period for convenience (where period=1./freq). As expected, there is a very prominent cycle with a length of about 11 years. period=1./freq; plot(period,power); axis([0 40 0 2e+7]); ylabel('Power'); xlabel('Period (Years/Cycle)');

Finally, we can fix the cycle length a little more precisely by picking out the strongest frequency. The red dot locates this point. hold on; index=find(power==max(power)); mainPeriodStr=num2str(period(index)); plot(period(index),power(index),'r.', 'MarkerSize',25);
text(period(index)+2,power(index),['Period =',mainPeriodStr]);

hold off;

Potrebbero piacerti anche