别再傻傻分不清了!MATLAB做频谱分析时,fft和fftshift到底该用哪个?(附代码对比)

张开发
2026/6/7 13:05:09 15 分钟阅读
别再傻傻分不清了!MATLAB做频谱分析时,fft和fftshift到底该用哪个?(附代码对比)
MATLAB频谱分析实战fft与fftshift的核心差异与选择策略第一次用MATLAB做频谱分析时盯着屏幕上两条几乎相同的曲线我花了整整三小时才意识到自己犯了一个低级错误——把fft和fftshift的结果混为一谈。相信很多信号处理新手都经历过这种困惑明明代码没报错频谱图却总感觉哪里不对劲。本文将用最直观的方式帮你彻底理清这两个函数的本质区别。1. 从视觉差异理解本质区别让我们从一个简单的实验开始。假设我们有一个100Hz的正弦波信号采样率设为2000Hz。当我们分别用fft和fftshift处理这个信号时得到的频谱图会呈现完全不同的视觉效果。fs 2000; % 采样频率 f_signal 100; % 信号频率 t 0:1/fs:1-1/fs; % 时间向量 signal sin(2*pi*f_signal*t); % 生成正弦波 N 1024; % FFT点数 fft_result abs(fft(signal, N))/N; % 标准FFT fft_shifted fftshift(fft_result); % 移位后的FFT f (0:N-1)*fs/N; % 标准频率轴 f_shifted (-N/2:N/2-1)*fs/N; % 移位后的频率轴现在让我们对比两种频谱图的典型特征特征fft频谱图fftshift频谱图零频位置最左侧正中间频率轴范围0到fs-fs/2到fs/2对称性右侧显示正频率左右对称显示正负频率直观性适合观察单边频谱适合观察双边频谱关键提示fftshift不会改变数据本身只是重新排列了频率分量的顺序。理解这一点对避免后续分析错误至关重要。2. 傅里叶变换的数学本质与MATLAB实现要真正理解这两个函数的区别我们需要回到傅里叶变换的数学定义。连续傅里叶变换的公式为$$ X(f) \int_{-\infty}^{\infty} x(t)e^{-j2\pi ft} dt $$这个变换天然地包含了从负无穷到正无穷的频率信息。但在数字信号处理中我们使用的是离散傅里叶变换(DFT)$$ X[k] \sum_{n0}^{N-1} x[n]e^{-j2\pi kn/N}, \quad k0,1,...,N-1 $$MATLAB的fft函数实现了快速傅里叶变换算法来计算DFT。默认情况下它输出的频率分量排列顺序是直流分量(0Hz)正频率分量(1Hz到fs/2)负频率分量(-fs/2到-1Hz)这种排列方式虽然数学上正确但不符合人类对频谱的直观认知。fftshift的作用就是重新排列这些分量让零频位于中间正负频率对称分布。3. 何时使用fft何时选择fftshift根据实际项目经验我总结出以下选择指南3.1 优先使用fft的场景功率谱密度估计计算信号功率时通常只需要正频率部分实时频谱监测减少计算量提高处理速度滤波器设计设计数字滤波器时通常关注正频率响应% 计算单边功率谱示例 fft_result fft(signal, N); psd abs(fft_result(1:N/21)).^2/(fs*N); f_psd (0:N/2)*fs/N;3.2 必须使用fftshift的情况需要观察负频率分量如调制信号分析零频需要居中显示如图像处理中的频域滤波对称性分析研究信号的共轭对称特性% 双边频谱分析示例 fft_result fft(signal, N); fft_shifted fftshift(fft_result); f_shifted (-N/2:N/2-1)*fs/N;实用技巧在绘制频谱图时使用axis tight命令可以自动调整坐标轴范围让频谱特征更突出。4. 实战案例不同信号类型的频谱分析让我们通过几个具体案例加深对这两个函数的理解。4.1 纯正弦波信号对于单一频率的正弦波fft和fftshift的结果在信息量上是等价的只是显示方式不同% 生成复合信号 f1 50; f2 120; signal sin(2*pi*f1*t) 0.5*sin(2*pi*f2*t); % 标准FFT分析 fft_result abs(fft(signal, N))/N; figure; subplot(2,1,1); plot(f(1:N/2), fft_result(1:N/2)); % 单边谱 title(单边幅度谱(fft)); % 移位后的FFT fft_shifted fftshift(fft_result); subplot(2,1,2); plot(f_shifted, fft_shifted); % 双边谱 title(双边幅度谱(fftshift));4.2 带直流分量的信号当信号包含直流分量时fftshift的优势就非常明显了signal_dc 2 sin(2*pi*f1*t); % 带直流分量的信号 % 标准FFT fft_dc abs(fft(signal_dc, N))/N; % 移位后的FFT fft_dc_shifted fftshift(fft_dc); figure; subplot(1,2,1); stem(f, fft_dc); % 注意直流分量在最左侧 title(fft结果 - 直流分量位置); subplot(1,2,2); stem(f_shifted, fft_dc_shifted); % 直流分量居中 title(fftshift结果 - 直流分量位置);4.3 复指数信号对于复信号负频率分量携带独立信息fftshift变得必不可少% 生成复指数信号 f_complex 150; signal_complex exp(1j*2*pi*f_complex*t); % 频谱分析 fft_complex abs(fft(signal_complex, N))/N; fft_complex_shifted fftshift(fft_complex); figure; plot(f_shifted, fft_complex_shifted); title(复信号的频谱(必须使用fftshift)); xlabel(Frequency (Hz));5. 常见误区与调试技巧在实际使用中有几个容易出错的点需要特别注意频率轴计算错误这是最常见的错误之一。fft和fftshift需要配合正确的频率轴才能得到有意义的结果。% 正确的频率轴生成方法 f_correct (0:N-1)*(fs/N); % 标准fft频率轴 f_shifted_correct (-N/2:N/2-1)*(fs/N); % 移位后的频率轴幅度归一化问题fft结果的幅度需要根据点数进行归一化才能反映真实的物理幅度。频谱泄露处理对于非整周期采样需要加窗函数减少泄露影响。% 加窗处理示例 window hann(length(signal)); % 汉宁窗 signal_windowed signal .* window; fft_windowed abs(fft(signal_windowed, N))/sum(window);频率分辨率混淆频率分辨率Δffs/N与采样时间TN/fs成反比。调试建议当频谱图看起来不正常时首先检查频率轴定义是否正确然后验证幅度是否经过适当归一化最后考虑是否需要加窗处理。在最近的一个ECG信号分析项目中我花了半天时间调试一个异常的频谱最终发现是因为忘记对fftshift结果使用正确的频率轴。这个教训让我养成了一个习惯每次使用fft/fftshift时都会先确认频率轴的定义是否正确。

更多文章