np.fft.fft默认对最后一维变换且不归一化,输出等长复数数组;幅值需除以n才具物理意义,频率轴须用fftfreq生成并配合fftshift对齐,实信号推荐rfft以节省资源。

fft 函数默认只做单次变换,不自动归一化
NumPy 的 np.fft.fft 返回的是未归一化的复数频谱,幅度值会随采样点数 n 线性放大。比如对一个单位正弦波做 fft,峰值不是 0.5(理论幅值),而是接近 n/2。如果不手动除以 n,后续计算功率谱、做幅度比较都会出错。
- 正确做法:用
np.fft.fft(x) / len(x)得到物理可解释的幅度 - 功率谱密度常用
np.abs(np.fft.fft(x))**2 / len(x) - 若后续要逆变换,
np.fft.ifft默认也不归一化,需配合len(x)手动缩放
fftshift 让零频分量居中,但仅改变数组顺序,不改变数据本身
原始 fft 输出是“零频在左,正频→负频”排列(即 [0, 1, ..., n//2-1, -n//2, ..., -1]),画图时频率轴不对称。用 np.fft.fftshift 可重排为“负频→零频→正频”,但注意它只是索引重排,不修改数值。
- 必须配套使用
np.fft.fftfreq生成原始频率轴,再用fftshift对其重排 - 示例:
f = np.fft.fftfreq(n, d=dt); f_shifted = np.fft.fftshift(f) - 如果只对频谱调用
fftshift却忘了对频率轴也做,画出来的图横轴就完全错位
实信号用 rfft 更省空间且避免冗余计算
真实采集的信号(如电压、音频)都是实数,其傅里叶变换具有共轭对称性:负频部分是正频的镜像。用 np.fft.rfft 只计算并返回非冗余的正频部分(含直流和 Nyquist 点),长度约为 n//2 + 1,比 fft 快约 2 倍且内存减半。
- 对应频率用
np.fft.rfftfreq(n, d=dt)生成,长度与rfft输出一致 - 不能直接用
ifft还原,得用np.fft.irfft - 若信号含明显直流偏移,建议先
x - np.mean(x),否则低频泄漏会掩盖细节
采样率和信号长度决定频率分辨率与泄漏风险
FFT 的频率分辨率是 1/(n * dt)(dt 为采样间隔),不是由采样率单独决定。同时,若信号周期不能被采样窗口整除,会发生频谱泄漏——能量扩散到邻近频率点,导致峰值变宽、幅度偏低。
- 加窗(如
np.hanning(n))能抑制泄漏,但会降低频率分辨率、引入幅度衰减,需事后补偿 - 补零(
np.fft.fft(x, n=2048))只提高插值密度,不提升真实分辨率 - 真正提升分辨率的唯一办法是延长采集时间(增大
n),而非提高采样率
实际处理时,最容易被忽略的是归一化和频率轴匹配——两个看似简单的步骤,一旦漏掉,整个频谱图就失去物理意义。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











