如何从信号中获取频率?

Fel*_*ein 2 python signals fft frequency

我正在寻找一种从信号中获取频率的方法。下面是一个例子:

signal = [numpy.sin(numpy.pi * x / 2) for x in range(1000)]
Run Code Online (Sandbox Code Playgroud)

此数组将代表录制声音的样本(x = 毫秒)

sin(pi*x/2) => 250 赫兹

我们如何从信号(点列表)到从这个数组中获取频率?

注意: 我阅读了许多 Stackoverflow 线程并观看了许多 youtube 视频。我还没有找到答案。请用简单的词。(我很感激每一个回答)

yat*_*atu 7

您正在寻找的东西被称为傅立叶变换


一点背景

让我们从正式定义开始:

傅里叶变换(FT)分解的函数(通常是时间的函数,或一个信号)转换成其构成频率

这本质上是一种数学运算,当应用于信号时,可以让您了解每个频率在时间序列中的存在程度。为了在这背后获得一些直觉,查看DFT的数学定义可能会有所帮助:

在此处输入图片说明

k这里是风靡起来t时的所有方式N-1来计算所有的DFT系数。

首先要注意的是,这个定义有点类似于两个函数的相关性,在这种情况下x(n)是负指数函数。虽然这看起来有点抽象,但通过使用欧拉公式并稍微修改定义,DFT 可以表示为与正弦波和余弦波的相关性,这将解释虚部和实部的部分DFT

所以请记住,这本质上是在计算相关性,每当复指数分解的相应正弦或余弦与 的匹配时,x(n)就会在 中出现峰值X(K),这意味着信号中存在这样的频率。


我们如何用 numpy 做同样的事情?

因此,在给出了非常简短的理论背景之后,让我们考虑一个示例,看看如何在 python 中实现这一点。让我们考虑以下信号

Fs = 150.0;  # sampling rate
Ts = 1.0/Fs; # sampling interval
t = np.arange(0,1,Ts) # time vector

ff = 50;   # frequency of the signal
y = np.sin(2*np.pi*ff*t)

plt.plot(t, y)
plt.xlabel('Time')
plt.ylabel('Amplitude')
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

现在,可以使用 来计算 DFT np.fft.fft,如前所述,它会告诉您现在在变换域中信号中每个频率的贡献是什么:

n = len(y) # length of the signal
k = np.arange(n)
T = n/Fs
frq = k/T # two sides frequency range
frq = frq[:len(frq)//2] # one side frequency range

Y = np.fft.fft(y)/n # dft and normalization
Y = Y[:n//2]
Run Code Online (Sandbox Code Playgroud)

现在,如果我们绘制实际频谱,您将看到我们在 50Hz 频率处得到一个峰值,从数学角度来说,它将是一个以 50Hz 基频为中心的 delta 函数。这可以在下面的傅立叶变换对表中进行检查。

所以对于上面的信号,我们会得到:

plt.plot(frq,abs(Y)) # plotting the spectrum
plt.xlabel('Freq (Hz)')
plt.ylabel('|Y(freq)|')
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明