添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
爱热闹的葫芦  ·  DataGridView 类 ...·  9 月前    · 
温柔的电梯  ·  tensorflow - ...·  1 年前    · 

傅里叶变换,一度被推上了玄学的位置。

这位说,了解了它,能改变你,认识世界的方式。那个说,我喜欢信号系统,但是看了2周的傅里叶变换,放弃了。

也有很多人,写了科普教程,有零基础教程、保证看懂教程、掐死教程。但是,当他们亮出数学公式的那一刻,很多人陷入沉思:我……是从哪里开始,就已经看不懂了……

这些现象,激发了我强烈的表演欲望,我要登上舞台,为大家表演。我的表演,如果你看不懂,请掐死我。

二、写博客:傅里叶变换进行时

我正写博客,没有骗你,真的在写,有图为证(是的,用vscode写博客第一人)。

此时正是深夜,我屋内的电脑,发出“嗡嗡”的散热声。同时,窗外的马路,飞驰而过一辆渣土车,发出“嘀~”一声刺耳的鸣笛。

我,是如何,听到,声音的。

物体振动发出的声音,在空气中传播,进入我的耳朵,推动我的耳膜,声音大就推的强,声音小就推的弱,经过一系列处理,我就听到了电脑和汽车。

仔细想一下,有点奇怪,我居然根据耳膜被推动的情况,分析出了声音里,包含电脑散热风扇和汽车喇叭两种物体。其实除此之外,我还听到了楼上放电视、窗外的虫子叫、电动车报警器响了……

这个声音发出和接收的场景,就如同你用手指在桌子上有规律、有轻重地敲击。我相信,你能听出这番敲击是打快板,那番敲击是非洲鼓。但是,你很难通过敲桌子的节奏,听出来:你的同事在敲键盘,同时路上响起了救护车的声音。

先给你3分钟的时间思考一下,我去上个厕所先。

人类几万年的历史,不知道是否有人想过这个问题,拿根棍子捅你的耳膜,你就能分辨出十几样不同的发声物体,这到底该怎么来解释呢?

其实,这——就是傅里叶变换(我能让你猜着,这突然地转场?)。

如下图所示:推动你耳膜的力度就是左侧的波形,你的大脑经过傅里叶变换,分析出了十几种不同的发声物体。

好了,现在拿出傅里叶变换的定义:

傅里叶变换,表示能将满足一定条件的某个函数表示成三角函数(正弦和/或余弦函数)或者它们的积分的线性组合。

定义看不懂没关系,只要能看懂前面说的,分辨声音的那个例就行。

关于什么是傅里叶,此处打个标记叫[A]。如果你看不懂,就说从[A]开始就糊涂了,来掐我时,好让我死得明白。

但是,有一点谈资我们要知道,这个理论是法国人傅里叶在1807年提出来的。那时,嘉庆皇帝刚抄了和珅的家没过几年。

三、描述一个波:都有独特的气质

你糊弄我?你拿人这种有灵性的生物,来举数学的例子,数学公式能解决道德问题吗?

再说,声音混在一起,就如同染料混在一个缸里,你还能分出来?我就不信了!

我感觉有人跟我对话,充满了质疑和不屑。

那好,我换一个例子,收音机大家都知道吧。

全国几百家广播台,各家都往外发送无线电波。

我们并非生活在多个平行宇宙。因此,这些电波没有VIP通道,肯定都是混在一起在空中传播的。就像下面这样:

那……收音机,可以收听指定电台的节目。

这个是机器,它的收音设备,没有你的耳朵那么复杂,也没有神经元,这一点儿灵性也没有,但它是可以分解指定波段的。

好了,继续看我表演,说一下声音的两个属性:频率、振幅。

3.1 声音的频率

声音是由振动产生的,振动一般都是……就……就像这样:

一个点围绕着某个相对固定的中心,周期性地移动。

比如,一个弹簧吊着一个小球,上下振动。

如果,一边记录时间,一边记录位置,其实它的形状就是弦曲线(我保证这个词,已是本文最专业的术语),也可以叫波。

有些物体振动的快,1秒钟反复来回1000次。有些物体振动的慢,1秒钟才往返1个周期。

这个单位时间内振动一个周期的次数,我们就叫 频率

因为材质不同,不同的物体振动的频率是不一样,波形也不一样。

下面是物理课上,敲击音叉振动的声波。

下面是用嘴吹试管的声波。

只要我们听到的声音不一样,基本上它们声波的频率也是不一样的。

就算都是口琴,低音区是这样的:

高音区是这样的:

我们发现,高音区比较密集,相同单位内振动的次数更多,也就是频率大。反之,低音区频率小,比较稀疏。

你听到的每种不同类型声音,都有自己固定的频率,就像每个地方菜的口味一样,是有差别的。此处打个标记叫[B],如果你看不懂,就说从[B]开始,就乱了,来告诉我。

3.2 声音的振幅

声音的振幅就是声音的大小。大小和频率没有任何关系。

频率是某个时间内,推了耳膜多少次。振幅是这次推动,花了多少力气。

还是拿音叉举例子,声音的振幅只影响音量,波形、频率都不变。你敲出原子弹爆炸的音量,它也是那个形状。

声音大时,音叉的波形:

声音小时,音叉的波形:

这很好理解,不管我小声说话,还是大声说话,你都能听出是我。但是,我大声说话,你会震得耳朵疼(耳膜遭受一记重拳)。

再来点儿谈资吧。我们人类能听到的频率范围是20Hz(1秒钟振动20个周期)到20000Hz。超过20000Hz为超声波,低于20Hz为次声波。我们常说,蝙蝠发出的超声波,不是因为它声音太小或太大,导致我们听不见。其实是因为它振动得太快,蝙蝠已经说了5000字了,但是我们只收到一个“的”。这是没有意义的。同样,我们人类能发出的声音频率也是有范围的,范围在250Hz-4000Hz之间,这是由我们人类声带的肉质(额……不知道为啥突然出来这个词)决定的。

振幅和频率的区别,此处打个标记叫[C]。

如果你了解了,频率和振幅这两个波的属性,后面就好说了。

四、说傅里叶变换吧:我不抗拒了!

傅里叶发现,这个世界上的人,对事物的理解不透彻,描述的也不科学。

世人都以时间为轴线,来描述事物。比如,描述一段1分钟的录音:第1秒说了什么,第2秒说了什么……。

世人摇摇头,叹了口气:傅里叶,你想咋着?

4.1 时域

傅里叶说,以时间作为参考的描述,叫时域分析。

比如下面这图,这是个时域图。我们看到这1秒内,它很忙,来来回回,从0到1秒跑着,从-1跑到1,反复了5次。所以,这段波的频率是5,最大振幅是1。整图描述的是,每一个时刻的信号值:

如果这段波,不是1秒,而是1个小时,那么它就是3600个这样的图拼在一起。

时域的概念,打个标记叫[D]。不懂的话,就看看表,再看看路上的汽车,刚才在你左边,1分钟后到了你的右边。2分钟后,它还在原地等红绿灯,每个时间都有对应的位置。这也是我们普通人认识世界的方式。

4.2 频域

还是那段波,而如果用频域来描述,那就是这样的:

横坐标表示频率,纵坐标表示振幅 。上面这个图表示:这里面有一段波,频率为5,振幅为1。

傅里叶告诉世人,我这个频域,可以抵得过时域的千年万年。两者说的是同一件事,只是分析的角度和描述手段不一样。

呵呵哈……哈呵呵,傅里叶冷笑着离开了,他连笑,都带着波形。

频域,打个标记叫[E]。

4.3 波的合成和分解

世界上的波,不会是上面说的那么单纯,实际上是很复杂的。

波,根据固定的频率振动,原本很单纯。只是,大家都在同一个空间内振动,相互之间发生了抵消和促进,相互融合,进行叠加,导致它很复杂。

波的叠加,打个标记叫[F]。不明白的话,赶紧评论区输入[F],让我知道,我会加强细节描述。

既然能叠加,那么能拆解吗?

其实,是可以的。不只是听觉,人类的味觉也做到了,你吃一口菜,可以尝出来里面有糖,有醋,有辣椒。它的理论基础就是,味觉具有一定的标准,辣就是辣,混到哪里都是辣。

波也一样,大家都是振动,震动就是弦曲线,只是频率不一样。

我们可以通过转啊转,各种组合,你护拢我,我护拢你,总能拼起来。

规律的波,并非一定得是“U”形,下面这几种情况,也都是规律的波形。

甚至,下面这个形状,也是规律的波形。可以拆解为若干组波的叠加。

二维空间里没有规律,就去从三维空间里面找。即便实在无法分解,我们也可以认为它的周期无限长,我有规律,只是本次循环还没到头呢?着啥急!

波的分解,不用明白具体是怎么分的。知道能分就行,打个标记叫[G]。

4.4 时域拆解频域

一段复杂的波,可以分解成,多段,规律的单纯波的集合。

然后,对这些规律的波从频域进行描述,就有了整段波的谱线图。

下图是一个综述。 f 指的是频率维度。这张图,很清晰地说明了波形、时域和频域的关系。很多教程,开局就拿出这张图,可解万难。但是,我说了这么久,才敢亮出来。

此图打个标记叫[H],还不明白来掐我。

4.5 频域复原时域

根据频域,也能复原成时域(此处用理想波,便于理解概念,还有相位等问题,不敢具体展开了)。

上面图里绿色的频率和振幅,可以描述一个波。如果把谱线上描述的波,依次画出来,然后做叠加。这样就复原了时域的波形。这个过程就像是泡发木耳。

波的复原,打个标记叫[I],有疑问请评论(别的平台复制本文可能不回复,但是掘金TF男孩一定给你回复,且回复的比你问的还要多)。

五、傅里叶变换有什么用?

傅里叶变换,在生物领域,你已经享受到它的益处了,你能分辨出一段声音里不同的声源,一口食物里不同的味道。

除此之外,我们可以拿时域转频域,对频域的特征进行二次加工,然后再恢复成时域,以此来做文章。

比如那些演唱会上调节声卡的人,如果你高音不足,可以给你升上去,低音太高,可以给你降下来。

举个例子,比如变声软件。把一段音频,分离出男声和女声,将男声改为女声的频率,然后还原回去,实现男声变女声。

再比如,声音压缩。将一些低频波形,合成一条。如下图蓝色线条,可以替代其下方的其他多条波形,而又不会影响人们的听觉判断,以此实现了数据的压缩。

除了在音频和信号的应用之外,在视觉上也有广泛应用,比如轮廓提取、美颜磨皮等等。

甚至,我还有一个想法,研发一款不会颠簸的汽车:

应用部分,如需讨论,打个标记叫[J]。

六、代码实践

如果,你已掌握了上面说的傅里叶变换。那么,下面,我们就要实践一下了。

实践的目的在于应用,表示我们已经可以利用代码,进行傅里叶变换了。这可以加深理解,并储备知识。

以下代码,采用python语言演示。

6.1 生成波形

傅里叶变换,是对波形做变换。因此,要变换我们首先得有一段波形。比如这一段音频,这是单词“stop”的声音波形(3个小高峰,s-tɒ-p):

信息的读取和绘制都很简单:

from scipy.io import wavfile
import matplotlib.pyplot as plt
# 读取音频数据
fs, audio_wave = wavfile.read("stop.wav") 
# 采样率 fs, 音频数据 audio_wave
plt.plot(audio_wave) # 绘制音频数据
plt.show()

这样看的不直观,我们选取开头的160个点,plt.plot(audio_wave[0:160])来绘制这一小段,这样看就是线条的波形了:

从总图看,开头那部分是一马平川。但是,当我们放大这部分细节时,我们看到的却是满眼的崎岖和坎坷。

我们看到上面的wavfile.read函数返回两个值,一个叫采样率,一个叫音频数据。

声音的读取和波形绘制,此处打个标记叫[K]。

6.1.1 采样率

采样率就是采样的频率,描述多长时间记录一次数据。

还记得打点计时器吗?

那个在纸上打点的频率,就叫采样率

比如,1秒钟打60个点,采样率就是60。

60的采样率,能记录上信息吗?

这得看对方信号有多快。

如果对方太慢,会导致一个地方频繁打点,其实打一个点和打100个点没有区别,这很浪费。

如果对方太快,可能会记录不全,甚至它跑了好多周期了,我们一个点都采不上。蝙蝠的超声波就是频率太快了,我们的耳膜采样不上。

下图是采样率为1000和100时,记录的图:

可见,信号不复杂时,采样率高和超高,没有什么变化,都能记录全了。区别只是,用1万个点来描述,还是用100个点来描述。

下图是采样率为20时,绘制的同一段信号的图:

采样率一旦比信号低(小于信号最高频的2倍)了,有些信息的细节就记录不上了。

对于录音机,我们说,它是否能把声音的细节记录上,主要看它的采样率高不高。

关于采样率,此处打个标记叫[L],你是否get全了呢?

为什么要了解这些概念?因为我们要制造声波数据,需要先了解它。

为什么要造数据(这自问自答,我也是不要脸了)?因为我们造的数据,是我们已知的参数,便于我们和求出的结果做对照。

要造数据,还需要了解弦函数sin(θ)

就是横轴上一个点,对应纵轴上一个值,把它们画出来,就是一个波:

6.1.2 绘制波形

现在,我们来搞一系列的横纵坐标点。

import numpy as np
#采样率,单位时间内采集多少次样本(1秒内记录1000次,采样率1kHz)
Fs = 1000 
#采样周期,频率的倒数,相邻两点的时间间隔,1秒打10个点,采样周期就是0.1秒
T = 1/Fs 
#信号长度,信号有多少个点
L = 1200 
# 时间轴X轴的集合,这批信号每次采集的时间点
t = np.arange(L)*T 
# 幅度值Y轴的集合,1200个点对应的Y轴的值
S = np.sin(2*np.pi*t)

上面代码,t是横轴坐标,S是纵轴坐标。我们先来看1秒内发生的故事,因为我们设置的是1秒一个周期,其他时间段都是循环的。

我们的采样率是1000,也就是1秒记录1000个点。

1秒内,t的值是[0.000,0.001,0.002,……,1.0],把一个(完整周期)分成了1000份。对这1000个点求函数的值,也就是S = [0,…0.5,…1,…0,…-0.5,…-1,…,0]

如果用代码画出来的话。

import matplotlib.pyplot as plt
plt.plot(t[:1000], S[:1000])
plt.show()

数据就是下图所示:

上面的例子中,1秒进行了一个周期,频率是1。

如果,我们要一个频率为5的波形,那又该怎么整呢?

很简单,让S = np.sin(2*np.pi*t*5),里面乘以5,再画出来,就是下图这样:

如果想要一个频率为8的波形呢?乘以8就可以了!

关于波形数据的生成和绘制,此处打个标记叫[M]。如果大脑过载的话,要及时上报啊。

下面,我们准备了一组复合波数据,作为测试样本。

这批样本,其实就是一段频率为5的波,叠加一段频率为20的波。

其中有点插曲(故意设计的),这个频率为20的波,他的振幅为0.5(频率5的振幅是1),波形是这样的。

两段波相加,混合起来是这样的:

S_5 = np.sin(2*np.pi*5*t)
S_20 = 0.5*np.sin(2*np.pi*20*t)
S_25 = S_5 + S_20

好了,这个就是我们自己造的测试数据。

下面,我们来做傅里叶变换,看看能不能分析出来它的组成。

关于波的叠加,此处打个标记叫[N]。

6.2 傅里叶变换 FFT

今天,我们是用傅里叶变换,不是写傅里叶变换。所以过程会很简单,简单到就3个字母fft

python库scipy.fftpack中有fft,它就是专门处理傅里叶变换的。

from scipy.fftpack import fft
# 完成傅里叶变换
Y = fft(S_25)
# 把结果画出来
p2 = np.abs(Y)
p1 = np.abs(Y)[:int(L/2)]
# Fs、L是之前生成波形时的采样率和信号长度
f = np.arange(int(L/2))*Fs/L 
plt.plot(f,2*p1/L) 
plt.show()

采用傅里叶变换,对测试波形进行分析,得出了这个谱线。

从图上我们看出,整段波里,存在2个频率的波形,一个频率为5,振幅为1;另一个频率为20,振幅是0.5(刚才就是按照这个规则造的假数据)。

这说明,分析的很对。

此时,我们可以玩耍的就多了。比如增大高频的频率,或者把低频的删除,然后再还原为波形,就做到了对声音的增强、提取和调整。

关于谱线,能看懂就行,此处打个标记叫[O],看不懂来掐我。

等会……这里面存在一个问题,那就是:这个分析结果,把时间维度给忽略了。

然而,时间是一个很重要的参考。

上面演示的是S20S5叠加的情况。如果要是S20追加S5呢?意思就是有先后顺序,就像这样:

S_20_5 = np.append(S_20, S_5)

这段波形,先是一段小声(振幅小)的高频(频率大),然后是一段大声(振幅大)的低频(频率小)。

我分析啊,应该先是女生小声嘀咕,然后男生大声呵斥。这个时间顺序里面,是包含着故事的。

波形分析里没有时间维度,就相当于食品说明里,只有组成成分,没有含量占比。这,没法判断它的口味和营养。

于是,短时傅里叶变换就出现了。

6.3 短时傅里叶变换 STFT

本文的毕业考核,就是最终能看懂下面这张图。

不着急,我慢慢说。

为了加上时间(序列)维度,才有了短时傅里叶。

其实,它的本质还是傅里叶,只是它从时域信号中,依次选取一段样本,进行傅里叶分析。分析完了,再合并起来,这样就有了时间维度了。

短时傅里叶变换的调用依然很简单,比傅里叶变换多一个字母,它是stft。传入的参数是要分析的波形数据,以及采样频率,返回值是:时间t、频率f、振幅Z。

from scipy.signal import stft
# 短时傅里叶变换
f, t, Z = stft(S_20_5, fs=1000)
# 把结果画出来
z = np.abs(Z)
plt.figure(figsize=(10,10))
plt.xlabel("author:handroid@126.com Time(s)")
plt.ylabel("frequency")
plt.ylim(ymin=0, ymax= 30)
plt.title("from https://juejin.cn/user/615370768790158")
c = plt.pcolormesh(t, f, z, cmap ='Greens', vmin = 0, vmax = 1)
plt.colorbar(c) 

由短时傅里叶变换得出数据生成的这个图,叫三维频谱图。

相比于谱线图,它加入了时间维度。

其中,横坐标是时间维度,这个时间可以不和波形图的时间对应。它和上面的fs采样点参数有关。纵坐标,则表示波形的频率。它虽然是一幅2维图,但可以表示3维的数据。

他的第三维度就是色块的色值,表示振幅。色值越亮,振幅越大

如何来分析这个图:

  • 从纵坐标入手:这段信号,包含2段频率,一段频率是20,另一段频率是5。其中20频率段振幅较小,5频率段的振幅较大。
  • 从横坐标入手:1.2s之前,只有高频信号;1.2s之后,高频消失,出现了低频信号,低频音量较大。
  • 从振幅入手:声音较大(色值较重)的主要出现在后半段,且是低频信号发出,推测是男生发火了。
  • 关于三维频谱图的解读,此处打个标记叫[P],看不懂就告诉我。

    好了,试试毕业考试吧,看下面这幅频谱图。这是一段音乐,上面两个波形是左右声道,下面火红的颜色是频谱,右侧坐标是音调(频率),比如C调,G5调等。

    这段音乐,哪段音域最活跃呢?这个歌手是女高音,还是男低音?

    七、保命条款

    朋友们,我讲的很初级,真的,一点都不谦虚。没讲相位,没讲函数的每一个参数,能省就省。这只是为了科普,让大家知道有这么一个东西,不但要知道,最好能吸收进去一些知识。学到的知识才是自己的。

    本文的目标读者,就是那些连sincos都还给初中数学老师的朋友们。他们真的找不到通俗的资料去学习,但是他们又有强烈的求知欲,尽管很多医生……不是,很多研究生,大呼他们已经尽力了。

    我不会再往深里讲了,因为本身我也不太懂。但是,我相信本文也是能帮到一些人的,尤其本文上传了将近50张图,很多动态图。

    如果有错误,欢迎大家指正,我会做修改,同时这也是我学习的机会。