fft.fft()和ifft()是最常用函数,但需注意输入长度影响精度、补零提升分辨率、实信号用rfft()、频域滤波须fftshift/ifftshift配对、频率轴需手动计算且与采样间隔d相关、多维数组需显式指定axis。

fft.fft() 和 fft.ifft() 是最常用的一对函数,但输入长度影响结果精度
NumPy 的 fft.fft() 默认对整个数组第一轴做 DFT,返回复数数组。它不自动归一化,也不补零——这意味着如果输入长度不是 2 的整数次幂,计算仍能进行,但可能引入频谱泄漏或降低频率分辨率。
实操建议:
- 对信号做
fft.fft()前,优先用np.fft.fftshift()配合绘图,否则零频分量在左侧,不符合常规频谱图习惯 - 若需提升频率分辨率,应补零(
np.pad(arr, (0, N-len(arr)), 'constant')),而非插值;补零不增加信息量,但让频点更密 - 真实信号通常为实数,可用
fft.rfft()节省一半计算量和内存,对应逆变换用fft.irfft() - 注意
fft.ifft()返回仍是复数,即使原信号为实数,需用np.real()提取(或加np.round(..., decimals=12)消除数值噪声)
频域滤波时忘记用 fftshift 导致滤波器错位
直接对 fft.fft() 结果的前半段设为 0(比如想滤掉低频),会误删高频分量——因为未平移前,正频率和负频率是“折起来”的:索引 0 是 DC,1 到 N//2−1 是正频率,N//2 是 Nyquist,N//2+1 到 N−1 是负频率。
正确做法是先 fft.fftshift(),再操作中间区域:
立即学习“Python免费学习笔记(深入)”;
freqs = np.fft.fftfreq(len(sig), d=dt) sig_fft = np.fft.fft(sig) sig_fft_shifted = np.fft.fftshift(sig_fft) # 现在 sig_fft_shifted[0] 对应最低负频,中间是 0Hz mask = np.abs(freqs) < 10 # 比如保留 ±10Hz 内 sig_fft_shifted[~mask] = 0 sig_filtered = np.fft.ifft(np.fft.ifftshift(sig_fft_shifted))
漏掉 ifftshift() 这一步,会导致相位混乱,重构信号严重失真。
采样率和频率轴必须手动算,fft.fftfreq() 不自动适配你的 dt
fft.fftfreq(n, d=1.0) 中的 d 是采样间隔(秒),不是采样率。常见错误是传入 fs=1000(采样率),却没转成 d=1/1000,结果频率轴整体缩放错 1000 倍。
使用场景中容易混淆的点:
- 若你有时间数组
t = np.linspace(0, 1, 1000, endpoint=False),则d = t[1] - t[0],别硬写 0.001 -
fftfreq()返回的频率顺序与fft()输出一致(未 shift),而fftshift()后需用fft.fftshift(fftfreq(...))对齐 - 对于实信号用
rfft(),对应频率轴应改用fft.rfftfreq(n, d),它只返回非负频率(含 Nyquist),长度为n//2 + 1
fft 模块默认按行处理多维数组,跨轴操作要显式指定 axis
对二维信号(如多通道 EEG、图像行方向滤波),fft.fft() 默认作用于 axis=-1(即每行独立变换)。若想对列做 FFT(比如逐时间点跨通道分析),必须传 axis=0。
容易踩的坑:
- 忘记指定
axis导致维度错乱,例如arr.shape == (100, 512)(100 个通道 × 512 采样点),想对每个通道做 FFT,应写np.fft.fft(arr, axis=1),而非默认的axis=-1(此时也对 512 维做,结果一样,但语义模糊) - 使用
fft.fft2()或fft.fftn()时,若只希望某几个轴参与,需用axes参数,如fft.fftn(arr, axes=(0, 2)) - 广播操作(如乘滤波器)前务必确认变换轴与滤波器维度对齐,否则触发
ValueError: operands could not be broadcast together
离散傅里叶变换本身不难调用,真正卡住人的永远是频率轴理解、shift/unshift 配对、以及多维数据中 axis 的隐式假设——这些地方一旦出错,结果看起来“差不多”,但实际相位全毁,滤波完全失效。


















