Skip to content

MATLAB - 快速傅里叶变换

MATLAB - 快速傅里叶变换 (FFT) 实践

Section titled “MATLAB - 快速傅里叶变换 (FFT) 实践”

快速傅里叶变换(FFT)是信号处理中的一个关键算法。其主要目的是将信号从其原始域(通常是时间)分解为其组成频率。实质上,FFT 告诉你信号中存在哪些频率以及它们的幅度是多少。

MATLAB 的 fft() 函数提供了该算法的高效实现。有效使用它的关键不仅仅是调用函数,还在于理解其输出以及如何针对有意义的频率轴正确地绘制它。

一个完整、实用的例子:分析含噪信号

Section titled “一个完整、实用的例子:分析含噪信号”

让我们逐步讲解一个完整、真实的例子。我们将创建一个包含两个不同正弦波的信号,添加一些随机噪声,然后使用 FFT 来识别原始频率。

% 信号参数
Fs = 1000; % 采样频率 (Hz)
T = 1/Fs; % 采样周期 (s)
L = 1500; % 信号长度
t = (0:L-1)*T; % 时间向量
% 创建一个包含 50 Hz 和 120 Hz 正弦波的信号
S = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);
% 向信号添加零均值随机噪声
X = S + 2*randn(size(t));
% 为了可视化我们的含噪信号,我们可以绘制它:
% plot(1000*t(1:50), X(1:50))
% title('含噪时域信号(前 50 毫秒)')
% xlabel('t (毫秒)')
% ylabel('X(t)')

此时,仅凭观察时域图,将很难识别出 50 Hz 和 120 Hz 的分量。

现在,我们将 fft 函数应用于我们的含噪信号 X。

Y = fft(X);

FFT 的输出 Y 是一个复值向量。为了获得幅度,我们取其绝对值。FFT 的结果对于实值输入也是对称的。我们通常只对频谱的前半部分(即单边频谱)感兴趣。

% 计算双边频谱 P2。
P2 = abs(Y/L);
% 基于 P2 和偶数值的信号长度 L 计算单边频谱 P1。
P1 = P2(1:L/2+1);
P1(2:end-1) = 2*P1(2:end-1);

这里,我们除以 L 来归一化幅度。然后我们取前半部分的点,并将除了第一个(直流分量,DC)和最后一个(奈奎斯特频率,Nyquist)分量之外的所有分量乘以 2,以守恒信号的能量。

为了使图表有意义,我们需要创建一个与频谱 P1 中的点相对应的频率向量。

% 定义频域 f
f = Fs*(0:(L/2))/L;
% 绘制单边幅度频谱 P1
plot(f, P1)
title('Single-Sided Amplitude Spectrum of X(t)')
xlabel('f (Hz)')
ylabel('|P1(f)|')
axis([0 200 0 1.2]) % 将视图聚焦在我们感兴趣的频率上

预期输出描述:生成的图表将显示一个从 0 Hz 开始的频率轴。尽管原始信号中存在严重的噪声,你仍将看到两个清晰、尖锐的峰值。一个位于 50 Hz,幅度约为 0.7;另一个位于 120 Hz,幅度约为 1.0,这成功识别了我们原始信号 S 的分量。

Y = fft(X, n) 计算 n 点 FFT。如果 X 的点数少于 n,它将用零填充。如果点数多于 n,它将被截断。零填充是一种提高 FFT 频率分辨率的常用技术,使其更容易精确定位峰值频率。

% 使用我们的原始信号 X(长度 1500)
% 计算 2048 点 FFT(零填充)
Y_padded = fft(X, 2048);

Y = fft(X, n, dim) 沿维度 dim 计算 FFT。这对于处理存储在矩阵的列或行中的多个信号非常有用。

% 创建一个以 2 个信号作为列的矩阵
signal1 = sin(2*pi*50*t)';
signal2 = sin(2*pi*150*t)';
X_matrix = [signal1, signal2];
% 计算每列的 FFT(dim=1 是默认值)
Y_matrix = fft(X_matrix);
% 要计算每行的 FFT,你可以使用:
% Y_matrix_rows = fft(X_matrix, [], 2);
  • 逆 FFT (ifft):要将信号从频域转换回时域,请使用 ifft 函数。
  • fftshift:fft 的原始输出将零频率(直流,DC)分量放在数组的开头。对于某些类型的分析和可视化,将直流分量置于中心会很有用。fftshift 函数可以实现这一点。
  • 频谱泄漏和加窗:当信号在测量窗口内不是周期性时,会导致其能量“泄漏”到相邻的频率分箱中,模糊峰值。为了缓解这种情况,你可以在执行 FFT 之前将信号乘以一个窗函数(例如 hann 或 hamming)。这是专业频谱分析中的关键一步。