信号处理新手必看:如何用Python实现STFT替代FFT分析非平稳信号?
如果你刚开始接触信号处理,很可能第一个学会的“大招”就是傅里叶变换(FFT)。它能将一个复杂的声音、一段脑电波,或者任何随时间变化的信号,分解成一个个不同频率的正弦波,让你一眼看清信号里“藏”着哪些频率成分。这感觉就像拿到了一把万能钥匙,很多问题迎刃而解。
但很快,你可能会遇到一个尴尬的局面:当你分析一段音乐、一段语音,或者机械振动信号时,FFT给出的频谱图看起来“一团糟”,或者根本无法解释信号在时间上的变化。比如,一段先有鸟鸣后有雷声的录音,FFT只能告诉你这段录音里包含了鸟鸣和雷声的所有频率,却无法告诉你鸟鸣在何时开始、雷声在何时响起。这就是FFT的“阿喀琉斯之踵”——它完美地揭示了频率,却彻底丢失了时间信息。
问题的根源在于信号的平稳性。FFT假设你分析的信号在整个时间段内,其统计特性(如频率成分)是不变的。然而,现实世界中绝大多数让我们感兴趣的信号,如语音、音乐、金融时间序列、生物医学信号(EEG/ECG),都是非平稳的,它们的频率内容会随着时间动态变化。这时,你需要一个能同时看清“何时”出现“何种”频率的工具。这就是短时傅里叶变换(STFT) 登场的时刻,它本质上是给FFT加了一个“滑动的窗口”,让我们得以一窥信号的时频全貌。本文将彻底抛弃MATLAB的视角,手把手带你用Python生态中的强大工具(librosa和scipy),从原理到实战,构建属于你自己的非平稳信号分析流程。
1. 核心理念:从全局频谱到时频局部化
理解STFT,关键在于理解“短时”和“加窗”这两个概念。我们放弃一次性分析整个漫长信号这种“上帝视角”,转而采取一种更务实的“局部观察”策略。
想象一下,你要分析一首长达五分钟的交响乐。FFT的做法是把整首曲子当作一个整体,一次性进行变换,结果得到的是这五分钟内所有乐器所有音符频率的总和,你无法区分小提琴独奏是在开头还是结尾。STFT则像是一个拿着放大镜沿着时间轴慢慢移动的乐评人。这个放大镜就是窗函数。他每次只观察一个很短的片段(比如0.1秒),对这个片段进行FFT,记录下这个瞬间有哪些频率。然后,他把放大镜稍微往前移动一点(可能会与之前观察的片段有重叠),再分析下一个瞬间。最终,他把所有瞬间的频谱结果按时间顺序排列起来,就得到了一张声谱图——一张以时间为横轴、频率为纵轴、颜色深浅表示能量强弱的图像。
这个过程中有几个关键参数决定了你观察的“清晰度”:
- 窗长:放大镜的宽度。窗越长,你对频率的分辨能力越强(能区分开两个非常接近的频率),但对时间变化的捕捉能力越弱(无法精确定位频率变化的瞬间)。
- 窗类型:放大镜的镜片材质。不同的窗函数(如汉明窗、汉宁窗、矩形窗)在时域和频域有不同的特性,主要影响频谱泄漏(能量扩散到邻近频率)的程度。
- 重叠长度:每次移动放大镜时,与上一次观察区域的重叠部分。更多的重叠能让时间轴上的变化更平滑,减少信息跳跃感,但也会增加计算量。
下表对比了FFT与STFT的核心差异,帮助你建立直观认识:
| 特性维度 | 傅里叶变换 (FFT) | 短时傅里叶变换 (STFT) |
|---|---|---|
| 核心输出 | 全局频谱(频率 vs. 幅度/相位) | 时频谱图(时间 vs. 频率 vs. 幅度) |
| 时间信息 | 完全丢失 | 保留,可定位频率成分的发生时刻 |
| 适用信号 | 平稳信号(频率成分不随时间变化) | 非平稳信号(频率成分随时间变化) |
| 分析视角 | 全局、整体 | 局部、滑动 |

34

被折叠的 条评论
为什么被折叠?



