4、傅里叶变换入门:从时域到频域,理解频谱分析

说实话,我刚入行那会儿,看示波器上的波形看得眼睛都快瞎了。一个信号在时间轴上扭来扭去,你根本不知道它里面到底藏着什么。直到我真正搞懂了傅里叶变换,才恍然大悟——原来那些乱七八糟的波形,不过是几个正弦波叠在一起罢了。

这一章,我们就来聊聊这个神奇的工具。它能把信号从时域搬到频域,让你一眼看穿信号的“底细”。

4.1 为什么我们需要频域?

先问个问题:给你一段音频,里面有人声、有吉他、有背景噪音。你在时域里能看到什么?

嗯,就是一条上下抖动的曲线。你分不清哪个是歌声,哪个是噪音。

但在频域里呢?每个频率分量都清清楚楚。人声在 300Hz-3kHz 附近,吉他泛音在更高频段,噪音可能集中在某个固定频率。你一看频谱图,就知道该砍掉哪部分。

我在做工业设备故障诊断时遇到过类似情况。电机振动信号在时域里看着很正常,但一转到频域,某个特定频率的幅值突然飙升——那就是轴承磨损的特征。没有频域分析,你根本发现不了。

核心思想:时域告诉我们“信号什么时候变化”,频域告诉我们“信号由哪些频率组成”。两者是同一信号的不同视角。

4.2 傅里叶变换的本质

傅里叶变换的数学公式长这样:

X(f) = ∫ x(t) · e^(-j2πft) dt

别被这个积分吓到。说白了,它干的事情就三步:

  1. 拿一个已知频率的正弦波,跟你的信号做乘法
  2. 把乘积积分(也就是求和)
  3. 看结果有多大——结果越大,说明信号里这个频率的成分越多

你想想看,如果信号里恰好有一个 100Hz 的分量,而你拿一个 100Hz 的正弦波去跟它相乘再积分,结果会很大。如果你拿 200Hz 的去乘,结果几乎为零。就这么简单。

我习惯把这个过程叫做“频率探针”——你拿不同频率的探针去戳信号,看哪个频率能引起“共振”。

4.3 从连续到离散:我们实际用的是 DFT

现实世界里的信号都是离散的采样点,不是连续的数学函数。所以我们需要离散傅里叶变换(DFT)。

公式变成这样:

X[k] = Σ x[n] · e^(-j2πkn/N)   (n = 0, 1, ..., N-1)

其中:

  • x[n] 是时域采样值
  • N 是采样点数
  • k 对应频率索引,k=0 是直流分量,k=1 是基频,以此类推

这里有个关键点:频率分辨率。它等于采样率除以 N。比如你以 1000Hz 采样,采了 1000 个点,那频率分辨率就是 1Hz。你想分辨出 0.5Hz 的差异?那就得采更多点。

实用技巧:我在做音频降噪时,通常把帧长设为 1024 或 2048 点。太短了频率分辨率不够,太长了时域定位不准。这个平衡点需要根据实际信号来调。

4.4 频谱图怎么看?

做完傅里叶变换,你得到的是复数。通常我们取它的幅值,画成频谱图。

横轴是频率,纵轴是幅值。一个典型的频谱图长这样:

幅值
  ↑
  |    ██
  |    ██
  |    ██    ██
  |    ██    ██    ██
  |    ██    ██    ██    ██
  +--------------------------------→ 频率
       0   100   200   300   (Hz)

看到那几个尖峰了吗?那就是信号里的主要频率成分。

我刚开始看频谱图时犯过一个错误:以为幅值最高的就是最重要的。其实不一定。有时候低频分量幅值很大,但那是直流偏置,不是有用信号。真正要关注的是那些跟你的应用相关的频段。

4.5 快速傅里叶变换(FFT)——工程界的救星

直接按 DFT 公式计算,复杂度是 O(N²)。N=1024 时还好,N=百万级时根本算不动。

FFT 的出现解决了这个问题。它把复杂度降到 O(N log N),快了不止一个数量级。

FFT 的核心思想是分治:把一个大 DFT 拆成两个小 DFT,再递归下去。具体实现有基-2、基-4 等算法,但作为使用者,你只需要知道:

  • 输入点数必须是 2 的幂(1024、2048、4096...)
  • 输出是对称的,前一半是正频率,后一半是负频率(通常只看前一半)
  • 幅值需要做归一化处理

避坑指南:我曾经在项目里直接用 FFT 的原始输出幅值去做阈值判断,结果发现数值忽大忽小。后来才意识到,FFT 输出的幅值跟采样点数 N 有关,必须除以 N/2 才能得到真实的幅值。这个坑,很多新手都会踩。

4.6 频谱泄露与窗函数

现实中的信号不可能是无限长的。我们只能截取一段来做 FFT。这个截断操作,会在频谱上引入“泄露”——本来应该集中在一个频率的能量,扩散到了相邻频率上。

怎么解决?加窗。

常用的窗函数有:

窗类型 主瓣宽度 旁瓣衰减 适用场景
矩形窗 窄 差(-13dB) 瞬态信号、频率成分间隔大
汉宁窗 中等 较好(-32dB) 通用、音频处理
海明窗 中等 好(-43dB) 语音、窄带信号
布莱克曼窗 宽 优秀(-58dB) 需要高动态范围

我个人习惯在降噪滤波器里用汉宁窗。它在主瓣宽度和旁瓣衰减之间取得了不错的平衡。如果你需要检测两个频率很近的信号,可以考虑矩形窗或凯泽窗。

4.7 本章知识体系

下面这张图帮你理清傅里叶变换的核心脉络:

傅里叶变换知识体系 傅里叶变换知识体系 傅里叶变换 时域 → 频域 离散化 → DFT FFT 加速 频谱分析 频谱泄露 窗函数 关键应用 • 降噪滤波器设计 • 信号特征提取 • 频率响应分析 • 系统辨识

4.8 动手试试:一个简单的 FFT 示例

光说不练假把式。下面这个 Python 代码,生成一个 50Hz + 120Hz 的混合信号,然后做 FFT 看看频谱:

import numpy as np
import matplotlib.pyplot as plt

# 参数设置
fs = 1000          # 采样率 1000Hz
T = 1.0            # 时长 1 秒
N = int(fs * T)    # 采样点数
t = np.linspace(0, T, N, endpoint=False)

# 生成信号:50Hz + 120Hz
f1, f2 = 50, 120
x = 0.7 * np.sin(2 * np.pi * f1 * t) + 1.2 * np.sin(2 * np.pi * f2 * t)

# 加汉宁窗
window = np.hanning(N)
x_windowed = x * window

# FFT
X = np.fft.fft(x_windowed)
freqs = np.fft.fftfreq(N, 1/fs)

# 只取正频率部分
half = N // 2
X_mag = np.abs(X[:half]) * 2 / N

# 打印前几个峰值
print("频率 (Hz) | 幅值")
print("-----------------")
for i in range(5):
    print(f"  {freqs[i]:.1f}    | {X_mag[i]:.4f}")

运行这段代码,你会看到在 50Hz 和 120Hz 处出现明显的尖峰。幅值分别是 0.7 和 1.2——跟原始信号完全一致。

小提示:注意代码里的 * 2 / N 这一步。这就是我之前说的归一化。不加的话,幅值会偏大 N/2 倍。

好了,傅里叶变换的基本概念就讲到这里。你掌握了时域到频域的转换思路,理解了 DFT 和 FFT 的区别,也知道了频谱泄露和窗函数是怎么回事。这些知识,是后面所有降噪滤波器设计的基础。