## MATLAB下fft(Fast Fourier Transform)函数的使用

时间:2024-04-04 08:21:12

直到现在才意识到,DFT或FFT无论是在信号处理、还是在图像分析、又或是模式识别中的地位和重要性,以至于在大学竟然没有自己写过信号的FFT的程序,果然出来混迟早是要还的,大学欠下的债现在该还了。花了一天看DFT、FFT,去证明蝶形运算、快速算法,又花了一天去写程序,去验证Fourier的理论,去实现自己的想法。
1、Syntax and Description
Y = fft(x) — returns the discrete Fourier Transform (DFT) of vector x,computed with a fast Fourier transform (FFT) algorithm. If the input x is a matrix, Y = fft(x) return the Fourier transform of each column of the matrix.
Y = fft(x,n) — returns the n-points DFT. fft(x) is equivalent to fft(x,n) where n is the size of x.If the length of x is less than n, x is padded with trailing zeros to length n. If the length of x is greater than n, the sequence x is truncated. When x is a matrix, the length of the columns are adjusted in the same manner.
Y = fft(x,[ ],dim) and Y = fft(x,n,dim) — applies the FFT operation across the dimension dim.
2、程序示例

clc
clear all
close all

Fs=1000;						% Sampling Frequency
Ts=1/Fs;						% Sampling Time
f=50;							% Frequence of Signal
N=256;							% Length of Signal
t=(0:N-1)*Ts;					% Time Vector
x=sin(2*pi*f*t);				% Sine Signal
subplot(311)
plot(t,x);
ylabel('x(t)'),xlabel('t/s'),title('时域信号')
grid on

NFFT=2^nextpow2(N);				% Next power of 2 from length of x.
y=fft(x,NFFT);            	    % 基-2快速傅里叶变换
X=abs(y);						% Compute Amplitude Spectrum of x
f=(0:N-1)/(N*Ts);         	    % Frency Vector
subplot(312)
plot(f,X);hold on
ylabel('X(f)'),xlabel('f/Hz'),title('频域信号')
grid on 
ind=find(X==max(X),1,'first');	%寻找最大值位置,返回1个linear inds:ind
x0=f(ind);						%根据位置得到横坐标(频率)
y0=X(ind);						%根据位置得到纵坐标(幅度)
plot(x0,y0,'ro');hold on
text(x0+1,y0-0.1,num2str(x0,'频率=%f')); 
		%   text(x,y,'string')在图形中指定的位置(x,y)上显示字符串string
ind=find(X==max(X),1,'last');	%寻找最大值位置,返回1个linear inds:ind
x0=f(ind);						%根据位置得到横坐标(频率)
y0=X(ind);						%根据位置得到纵坐标(幅度)
plot(x0,y0,'ro');hold off
text(x0-10,y0+10,num2str(x0,'频率=%f')); 
		%   text(x,y,'string')在图形中指定的位置(x,y)上显示字符串string

x1=ifft(y,NFFT);       			 % Inverse FFT
subplot(313)
plot(t,x1);
ylabel('x1(t)'),xlabel('t/s'),title('逆变换信号')
grid on

3、程序解读
先从理论分析sin(2Πft)的频谱(幅度谱)长啥样,根据理论有:
## MATLAB下fft(Fast Fourier Transform)函数的使用
由上式可以得出结论:sin(2Πft)的FT是复数,我们接下来主要研究它的幅度谱。显然,正弦函数的幅度谱就是在f0处和-f0处的两条幅度都为(正)无穷大的冲激(不考虑冲激的相位,仅考虑模值)。
但是问题来了,程序始终不可能求连续的FT,计算机也只能求DFT或者FFT,所以信号会被离散、截短,会将没有信号的位置认为是信号的周期延拓。这会导致频谱泄露,以至于频谱幅度不会是无穷大,只能说是很大,中心频率附近的频率分得泄露的频谱(能量)从而幅度不为0。
时域信号以Fs进行采样离散化,频域会以Fs周期延拓;时域信号以观测时间NTs周期延拓,频域将以1/(NTx)(频域分辨率)为间隔离散化。由于计算机执行的是DFT,我们只能得到主值序列【0到N-1的x(n)和X(k)】,所以在-f0处的谱线就会出现在Fs-f0。
接下来由两个实验加强理解傅里叶变换。

(1)改变采样频率Fs,采样点数N=256,信号频率f0=50Hz。
a、Fs=1000Hz(信号频率的20倍),结果如下:

## MATLAB下fft(Fast Fourier Transform)函数的使用

b、Fs=500Hz(信号频率的10倍),结果如下:
## MATLAB下fft(Fast Fourier Transform)函数的使用

c、Fs=100Hz(Nyquist频率),其实对于正弦信号来说,在Nyquist采样频率下已经失真。结果如下:
## MATLAB下fft(Fast Fourier Transform)函数的使用

(2)调整采样点数N,f0=50Hz。
a、N=256,结果如下:

## MATLAB下fft(Fast Fourier Transform)函数的使用
b、N=512,结果如下:

## MATLAB下fft(Fast Fourier Transform)函数的使用
c、N=1024,结果如下:
## MATLAB下fft(Fast Fourier Transform)函数的使用

虽然实验不够完善,但是也能粗略的说明问题。(1)中主要改变抽样频率,可以发现抽样频率必须要远大于由采样定理所确定的采样频率,那毕竟是“理论上”的极限,这样才能有很高得保真度;(2)中主要改变信号得观测长度,取得得观测点数N越多,采样信号与原始信号(时间上无始无终)越接近,因为截短而造成得频谱泄露程度就越轻。
完成!!!