傅里叶变换入门:从“把声音拆成音符”说起
励志让小白也能看懂数学建模算法!如果想看更详细的代码解析,可以看我的资源上传,里面有配套的更为详细的代码解析。
1. 背景溯源:傅里叶的热传导与“万物皆正弦”的猜想
1807年,法国数学家让-巴蒂斯特·约瑟夫·傅里叶(Jean-Baptiste Joseph Fourier)向巴黎科学院提交了一篇关于热传导的论文——他想解决一个难题:如何计算物体内部的温度分布?当时的物理学家用“微分方程”描述热传导,但复杂形状的物体(比如方形铁棒)的方程很难解。傅里叶提出了一个大胆的猜想:
“任何周期函数,无论多么复杂,都可以分解成一系列正弦函数和余弦函数的和。”
换句话说,热传导的温度分布(随时间和空间变化的信号),可以拆成“不同频率的正弦波的叠加”。这个猜想在当时引发了争议——拉格朗日等学者认为“只有连续可导的函数才能这样分解”,但傅里叶用实验证明:即使是有尖峰或间断点的函数(比如方波),也能通过正弦波的叠加逼近。
1822年,傅里叶出版《热的解析理论》(Théorie analytique de la chaleur),正式确立了“傅里叶级数”的理论。后来,学者们将其推广到非周期信号(比如单次脉冲),形成了我们今天说的“傅里叶变换”。
傅里叶的思想彻底改变了人类对“信号”的理解——从“时间域”(看信号随时间的变化)到“频率域”(看信号的频率组成),就像从“听一首歌的旋律”到“看这首歌的乐谱(音符组成)”。
2. 核心思想:时域到频域的“翻译术”——复杂信号的“正弦分解”
假设你有一个复杂的信号(比如一段音乐、一个心电图、一张图片),傅里叶变换的核心是做两件事:
分解:把时域(时间作为变量)的信号拆成一系列正弦波(不同频率、振幅、相位)的叠加;合成:用这些正弦波可以重新拼出原来的信号。
用一个比喻:
时域:你听一首钢琴曲,感受到的是“音符随时间的流动”(比如“do→re→mi→fa”);频域:你看这首曲的乐谱,看到的是“每个音符的频率(do是261.6Hz,re是293.7Hz)和强度(音量)”。
傅里叶变换就是“将钢琴曲转换成乐谱”的翻译工具——它把时域的“时间流动”翻译成频域的“频率组成”,让我们能更轻松地分析信号的本质(比如去掉杂音、压缩数据)。
3. 基础铺垫:从周期信号到傅里叶级数
傅里叶变换的起点是周期信号——即随时间重复的信号(比如正弦波、方波、三角波)。我们先学如何分解周期信号,再推广到非周期信号。
3.1 周期信号的定义:重复的“时间pattern”
一个信号x(t)x(t)x(t)是周期信号,当且仅当存在一个正数TTT(称为周期),使得对所有时间ttt,都有:
正弦波x(t)=Asin(ω0t)x(t) = Asin(omega_0 t)x(t)=Asin(ω0t)的周期是T=2π/ω0T = 2pi/omega_0T=2π/ω0(ω0=2πf0omega_0 = 2pi f_0ω0=2πf0是角频率,$ f_0 = 1/T $是频率,单位Hz);方波(比如“0→1→0→1→…”重复)的周期是TTT,占空比50%。
3.2 傅里叶级数的三角形式:正弦余弦的“合唱”
傅里叶级数的三角形式是:
omega0=2π/Tomega_0 = 2pi/Tomega0=2π/T:基频(周期信号的最低频率);nω0nomega_0nω0:n次谐波(基频的整数倍频率,比如n=1是基频,n=2是二次谐波,依此类推);a0/2a_0/2a0/2:直流分量(信号的平均值,即不随时间变化的部分);ana_nan、bnb_nbn:谐波系数(表示第nnn次谐波的“强度”)。
这个公式的意思是:任何周期信号都可以分解成“直流分量”+“基频正弦/余弦波”+“二次谐波正弦/余弦波”+…的和。
比如方波(周期TTT,幅度AAA,占空比50%)的傅里叶级数是:
3.3 傅里叶级数的系数:正交性的“魔法”
要分解周期信号,关键是求系数a0a_0a0、ana_nan、bnb_nbn。这里用到三角函数的正交性——即不同频率的正弦/余弦波在一个周期内的积分等于0(互不干扰),相同频率的积分等于一个常数(可以单独计算)。
正交性的核心结论(对周期TTT的信号):
3.∫0Tcos(mω0t)cos(nω0t)dt={T/2,m=n0,meqnint_{0}^{T} cos(momega_0 t) cos(nomega_0 t) dt =
4. ∫0Tsin(mω0t)sin(nω0t)dt={T/2,m=n0,meqnint_{0}^{T} sin(momega_0 t) sin(nomega_0 t) dt =
5. ∫0Tcos(mω0t)sin(nω0t)dt=0int_{0}^{T} cos(momega_0 t) sin(nomega_0 t) dt = 0∫0Tcos(mω0t)sin(nω0t)dt=0(对任意m,nm,nm,n)
简单来说:不同频率的正弦/余弦波“互不重叠”,相同频率的“重叠”。利用这个性质,我们可以单独求出每个系数:
直流分量系数$ a_0 :信号在一个周期内的平均值:信号在一个周期内的平均值:信号在一个周期内的平均值a0=2T∫0Tx(t)dta_0 = frac{2}{T} int_{0}^{T} x(t) dta0=T2∫0Tx(t)dt$
余弦项系数ana_nan:信号与cos(nω0t)cos(nomega_0 t)cos(nω0t)的“相关性”
正弦项系数bnb_nbn:信号与sin(nω0t)sin(nomega_0 t)sin(nω0t)的“相关性”
3.4 傅里叶级数的复数形式:更简洁的“数学语言”
三角形式的傅里叶级数虽然直观,但计算起来麻烦。我们可以用欧拉公式(复数的核心公式)将其简化为复数形式:
利用欧拉公式,余弦和正弦可以表示为:
将其代入三角形式的傅里叶级数,整理后得到复数形式的傅里叶级数:
复数形式的优点:
6. 更简洁(只用一个求和式,不用分开余弦和正弦);
7. 容易推广到傅里叶变换(非周期信号);
8. XnX_nXn包含了振幅和相位信息:
振幅:∣Xn∣=Re(Xn)2+Im(Xn)2|X_n| = sqrt{ ext{Re}(X_n)^2 + ext{Im}(X_n)^2}∣Xn∣=Re(Xn)2+Im(Xn)2(表示第nnn次谐波的强度);相位:∠Xn=arctan(Im(Xn)Re(Xn))angle X_n = arctanleft( frac{ ext{Im}(X_n)}{ ext{Re}(X_n)}
ight)∠Xn=arctan(Re(Xn)Im(Xn))(表示第nnn次谐波的“时间偏移”)。
3.5 例子:方波的傅里叶级数与吉布斯现象
我们用50%占空比的方波验证傅里叶级数:方波的定义:x(t)=Ax(t) = Ax(t)=A(当0<t<T/20 < t < T/20<t<T/2),x(t)=−Ax(t) = -Ax(t)=−A(当T/2<t<TT/2 < t < TT/2<t<T),周期TTT。
计算复数系数XnX_nXn:
当nnn为偶数时,e−jnπ=1e^{-jnpi} = 1e−jnπ=1,所以Xn=0X_n = 0Xn=0(偶数次谐波消失);当nnn为奇数时,e−jnπ=−1e^{-jnpi} = -1e−jnπ=−1,所以Xn=2AjnπX_n = frac{2A}{jnpi}Xn=jnπ2A(奇数次谐波保留)。
因此,方波的复数形式傅里叶级数为:
吉布斯现象:当我们用傅里叶级数的部分和(比如取前$ N 项)逼近方波时,在∗∗间断点∗∗(比如项)逼近方波时,在**间断点**(比如项)逼近方波时,在∗∗间断点∗∗(比如 t = T/2 处,方波从处,方波从处,方波从 A 跳到跳到跳到 -A )附近会出现∗∗振荡∗∗,振幅约为跳变的9)附近会出现**振荡**,振幅约为跳变的9%(比如方波跳变是)附近会出现∗∗振荡∗∗,振幅约为跳变的9 2A $,振荡幅度约为0.18A0.18A0.18A)。
吉布斯现象是傅里叶级数的固有特性——无论取多少项,振荡都不会消失,只会“收缩”到间断点附近。这告诉我们:傅里叶级数是“逼近”信号,不是“完全等于”信号(除非取无穷多项)。
4. 进阶:非周期信号与傅里叶变换
现在,我们要处理非周期信号——即不重复的信号(比如单次脉冲、语音中的一个字、图像中的一个像素)。非周期信号可以看成“周期$ T $趋近于无穷大的周期信号”,我们需要将傅里叶级数推广到这种情况。
4.1 非周期信号的困境:周期“无穷大”怎么办?
对于周期信号,我们有:
基频ω0=2π/Tomega_0 = 2pi/Tω0=2π/T;谐波频率是nω0nomega_0nω0(离散的,比如ω0,2ω0,3ω0,…omega_0, 2omega_0, 3omega_0, dotsω0,2ω0,3ω0,…);傅里叶级数是离散频谱(只有谐波频率处有值)。
当周期T→∞T o inftyT→∞时:
9. 基频ω0→0omega_0 o 0ω0→0(因为ω0=2π/Tomega_0 = 2pi/Tω0=2π/T);
10. 谐波频率nω0nomega_0nω0变成连续的频率ωomegaω(因为nω0=n⋅(2π/T)→ωnomega_0 = n cdot (2pi/T) o omeganω0=n⋅(2π/T)→ω,当T→∞T o inftyT→∞);
11. 离散的求和∑n=−∞∞sum_{n=-infty}^{infty}∑n=−∞∞变成连续的积分∫−∞∞dωint_{-infty}^{infty} domega∫−∞∞dω;
12. 复数系数XnX_nXn(与1/T1/T1/T成正比)会趋近于0(因为T→∞T o inftyT→∞),所以我们需要定义一个“密度”函数来描述频谱——这就是傅里叶变换。
4.2 傅里叶变换的定义:从“求和”到“积分”的推广
对于非周期信号x(t)x(t)x(t),傅里叶变换(正变换)的定义是:
傅里叶逆变换(从频域回到时域)的定义是:
注意:
13. X(ω)X(omega)X(ω)称为频谱密度函数(简称“频谱”),它是连续函数(非周期信号的频谱是连续的);
14. 逆变换中的1/(2π)1/(2pi)1/(2π)是“归一化因子”(保证正变换和逆变换的一致性);
15. ω=2πfomega = 2pi fω=2πf是角频率(单位rad/s),fff是频率(单位Hz)。
4.3 频谱的意义:振幅谱与相位谱
傅里叶变换X(ω)X(omega)X(ω)是复数函数,它包含了信号的振幅信息和相位信息:
振幅谱:∣X(ω)∣=Re(X(ω))2+Im(X(ω))2|X(omega)| = sqrt{ ext{Re}(X(omega))^2 + ext{Im}(X(omega))^2}∣X(ω)∣=Re(X(ω))2+Im(X(ω))2表示“频率$ omega $处的信号强度”(比如“100Hz的分量有多大”);相位谱:∠X(ω)=arctan(Im(X(ω))Re(X(ω)))angle X(omega) = arctanleft( frac{ ext{Im}(X(omega))}{ ext{Re}(X(omega))}
ight)∠X(ω)=arctan(Re(X(ω))Im(X(ω)))表示“频率$ omega $处的信号相对于参考正弦波的时间偏移”(比如“100Hz的分量比参考正弦波晚0.1秒到达”)。
举个例子:矩形脉冲信号(非周期)矩形脉冲的定义:x(t)=Ax(t) = Ax(t)=A(当∣t∣<τ/2|t| < au/2∣t∣<τ/2),x(t)=0x(t) = 0x(t)=0(当∣t∣>τ/2|t| > au/2∣t∣>τ/2),其中τ auτ是脉冲宽度。
计算傅里叶变换X(ω)X(omega)X(ω):
其中Sa(x)=sin(x)/x ext{Sa}(x) = sin(x)/xSa(x)=sin(x)/x是抽样函数(Sinc函数),它的形状是“主瓣+旁瓣”:
主瓣宽度:2⋅(2π/τ)=4π/τ2 cdot (2pi/ au) = 4pi/ au2⋅(2π/τ)=4π/τ(脉冲越窄,主瓣越宽,频域越分散);旁瓣振幅:随着ωomegaω增大,旁瓣振幅逐渐减小(表示高频分量的强度越来越弱)。
这个例子验证了不确定性原理:信号在时域越窄($ au $越小),在频域越宽(主瓣越宽);反之亦然。比如:
时域中“瞬间的脉冲”(τ→0 au o 0τ→0),频域中会覆盖所有频率(白噪声);频域中“单一频率的正弦波”(X(ω)=δ(ω−ω0)X(omega) = delta(omega – omega_0)X(ω)=δ(ω−ω0),冲激函数),时域中是“无限长的正弦波”。
5. 完整流程:傅里叶变换的“分步指南”
现在,我们总结用傅里叶变换分析信号的完整步骤:
5.1 步骤1:判断信号类型——周期还是非周期?
周期信号:存在T>0T > 0T>0,使得x(t)=x(t+T)x(t) = x(t + T)x(t)=x(t+T)(比如正弦波、方波);非周期信号:不存在这样的TTT(比如单次脉冲、语音片段)。
5.2 步骤2:周期信号→傅里叶级数
如果是周期信号,用傅里叶级数分解:
16. 计算基频:ω0=2π/Tomega_0 = 2pi/Tω0=2π/T;
17. 计算复数系数XnX_nXn(或三角系数a0,an,bna_0, a_n, b_na0,an,bn);
18. 画出离散频谱(横坐标是频率nω0nomega_0nω0,纵坐标是振幅∣Xn∣|X_n|∣Xn∣或相位∠Xnangle X_n∠Xn);
19. 分析频谱:看主要谐波频率(比如方波的奇数次谐波),以及各谐波的强度。
5.3 步骤3:非周期信号→傅里叶变换
如果是非周期信号,用傅里叶变换:
20. 计算傅里叶正变换:X(ω)=∫−∞∞x(t)e−jωtdtX(omega) = int_{-infty}^{infty} x(t) e^{-jomega t} dtX(ω)=∫−∞∞x(t)e−jωtdt;
21. 计算振幅谱∣X(ω)∣|X(omega)|∣X(ω)∣和相位谱∠X(ω)angle X(omega)∠X(ω);
22. 画出连续频谱(横坐标是频率ωomegaω,纵坐标是振幅或相位);
23. 分析频谱:看主要频率范围(比如矩形脉冲的主瓣宽度),以及高频分量的强度。
5.4 步骤4:频域分析——从频谱图读“信号密码”
频谱图是傅里叶变换的“输出报告”,我们可以从图中得到以下信息:
24. 信号的主要频率分量:振幅谱的峰值对应的频率(比如语音信号的基频约100-300Hz,泛音约1-3kHz);
25. 信号的带宽:振幅谱的主瓣宽度(比如矩形脉冲的带宽是$ 2pi/ au $);
26. 信号的相位特征:相位谱的变化(比如图像的相位谱包含“形状信息”,振幅谱包含“亮度信息”);
27. 噪声的位置:如果频谱图中有“异常的峰值”(比如50Hz的市电干扰),可以用滤波器去掉这些频率。
6. 适用边界与局限性:傅里叶变换不是“万能钥匙”
傅里叶变换是强大的工具,但它有适用条件和局限性,小白需要知道什么时候该用,什么时候不该用。
6.1 傅里叶变换的适用条件:狄利克雷条件
傅里叶变换要求信号满足狄利克雷条件(Dirichlet Conditions):
28. 绝对可积:信号在时域的绝对值积分有限,即∫−∞∞∣x(t)∣dt<∞int_{-infty}^{infty} |x(t)| dt < infty∫−∞∞∣x(t)∣dt<∞(保证傅里叶变换的积分收敛);
29. 有限个极值点和间断点:信号在任意有限区间内,只有有限个极大值/极小值和有限个间断点,且每个间断点的跳变是有限的(比如方波的间断点跳变是2A2A2A,有限)。
大多数实际信号(比如语音、图像、通信信号)都满足狄利克雷条件,但以下信号不满足:
无限长的正弦波(∫−∞∞∣sin(ω0t)∣dt=∞int_{-infty}^{infty} |sin(omega_0 t)| dt = infty∫−∞∞∣sin(ω0t)∣dt=∞,不绝对可积);无限振荡的信号(比如sin(1/t)sin(1/t)sin(1/t),在t→0t o 0t→0时无限振荡,有无限个极值点)。
对于不满足绝对可积的信号,我们可以用广义傅里叶变换(分布理论)处理,比如:
正弦波sin(ω0t)sin(omega_0 t)sin(ω0t)的傅里叶变换是jπ[δ(ω+ω0)−δ(ω−ω0)]jpi [delta(omega + omega_0) – delta(omega – omega_0)]jπ[δ(ω+ω0)−δ(ω−ω0)](冲激函数,表示“只有±ω0pmomega_0±ω0频率处有值”)。
6.2 傅里叶变换的局限性:无法处理“时变频率”
傅里叶变换的最大局限性是:它是“全局变换”,无法同时得到时域和频域的“局部信息”。
比如Chirp信号(频率随时间线性增加的信号,比如“呜——”的上升音):
时域:信号的频率从低到高变化(比如从100Hz升到1000Hz);傅里叶变换的频域图:显示一个宽的频率带(100Hz到1000Hz),但看不出频率随时间的变化(所有时间的频率都混在一起)。
换句话说,傅里叶变换只能告诉我们“信号包含哪些频率”,但不能告诉我们“这些频率在什么时候出现”。
6.3 替代方案:短时傅里叶变换与小波变换
为了处理非平稳信号(频率随时间变化的信号),我们需要局部化的傅里叶变换:
30. 短时傅里叶变换(STFT):把信号分成“短时间窗”(比如20ms),对每个窗内的信号做傅里叶变换,得到“时间-频率”二维图(比如“t=0.1s时,频率是200Hz;t=0.2s时,频率是500Hz”);
31. 小波变换:用“可变宽度的窗”(小尺度窗分析高频信号,大尺度窗分析低频信号),比STFT更灵活,适合分析突变信号(比如心电信号中的早搏)。
7. 总结:傅里叶变换的“初心”——让复杂信号“变简单”
傅里叶变换的本质是**“视角转换”**:
从“时间的视角”(看信号随时间的变化),转到“频率的视角”(看信号的频率组成);把复杂的“时间曲线”,分解成简单的“正弦波叠加”。
它的应用无处不在:
通信:调制解调(将信号从低频转到高频,方便传输);信号处理:滤波(去掉杂音,比如去掉50Hz的市电干扰);图像压缩:JPEG算法用傅里叶变换的变种(离散余弦变换,DCT)压缩图像(保留低频分量,去掉高频分量);医学:CT扫描用傅里叶变换重建图像(将X射线的投影数据转换成图像)。
对于小白来说,傅里叶变换的难点不是公式,而是**“从时域到频域的思维转换”**——当你能把“听音乐”变成“看乐谱”,把“看波形”变成“看频谱”,你就真正入门了傅里叶变换。
最后:给小白的建议
先理解思想,再记公式:傅里叶变换的核心是“正弦分解”,公式是思想的数学表达,不要死记硬背;用例子验证:比如用方波、矩形脉冲的例子,手动计算傅里叶级数/变换,看频谱图的变化;联系实际:比如用手机的“频谱分析仪”APP,录一段语音,看它的频谱(你会发现元音的频谱有明显的峰值,辅音的频谱是宽带的);接受局限性:傅里叶变换不是万能的,遇到非平稳信号时,要学STFT或小波变换。
傅里叶变换是“数学的眼睛”——它让我们看到了信号的“另一面”,而这一面,往往是更本质的。
案例介绍
生成一个包含两个正弦波叠加的模拟信号,使用傅里叶变换分解出原始信号的频率成分。
import numpy as np
import matplotlib.pyplot as plt
def generate_signal(duration, sampling_rate):
"""
生成模拟信号:两个不同频率的正弦波叠加
:param duration: 信号时长 (秒)
:param sampling_rate: 采样率 (Hz)
:return: 时间序列, 模拟信号
"""
# 生成时间轴
time = np.linspace(0, duration, int(duration * sampling_rate), endpoint=False)
# 生成两个正弦波:f1=5Hz, f2=15Hz
signal = np.sin(2 * np.pi * 5 * time) + np.sin(2 * np.pi * 15 * time)
return time, signal
def compute_fourier_transform(signal, sampling_rate):
"""
计算信号的傅里叶变换
:param signal: 输入信号
:param sampling_rate: 采样率 (Hz)
:return: 频率轴, 傅里叶变换结果
"""
# 计算傅里叶变换
fft_result = np.fft.fft(signal)
# 计算频率轴
freq = np.fft.fftfreq(len(signal), 1/sampling_rate)
# 取绝对值得到振幅谱
amplitude = np.abs(fft_result) / len(signal) * 2 # 归一化并取双边谱振幅
return freq, amplitude
def plot_results(time, signal, freq, amplitude):
"""
绘制原始信号和傅里叶变换结果
:param time: 时间轴
:param signal: 原始信号
:param freq: 频率轴
:param amplitude: 振幅谱
"""
# 创建画布
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 6))
# 绘制原始信号
ax1.plot(time, signal)
ax1.set_title('Original Signal')
ax1.set_xlabel('Time (s)')
ax1.set_ylabel('Amplitude')
# 绘制傅里叶变换结果 (仅显示正频率)
positive_freq_indices = np.where(freq >= 0)
ax2.plot(freq[positive_freq_indices], amplitude[positive_freq_indices])
ax2.set_title('Fourier Transform (Amplitude Spectrum)')
ax2.set_xlabel('Frequency (Hz)')
ax2.set_ylabel('Amplitude')
# 调整布局
plt.tight_layout()
# 显示图像
plt.show()
def main():
"""
主程序
"""
# 信号参数
duration = 2 # 信号时长 2 秒
sampling_rate = 100 # 采样率 100 Hz
# 生成模拟信号
time, signal = generate_signal(duration, sampling_rate)
# 计算傅里叶变换
freq, amplitude = compute_fourier_transform(signal, sampling_rate)
# 绘制结果
plot_results(time, signal, freq, amplitude)
# 执行主程序
if __name__ == "__main__":
main()
