在Python中理解FFT输出

3

我正在尝试理解scipy.fftpack.fft的输出。我创建了一个信号并对其进行fft。以下是fft的代码:

import numpy as np
from scipy.fftpack import fft
import matplotlib.pyplot as plt

# Number of samplepoints
N = 600
# sample spacing
T = 1.0 / 800.0
x = np.linspace(0.0, N*T, N)
y = 5.0 * np.sin(50.0 * 2.0*np.pi*x) + 1.0*np.sin(80.0 * 2.0*np.pi*x) #unit is V
yf = fft(y)
xf = np.linspace(0.0, 1.0/(2.0*T), N/2)

plt.close()
plt.plot(xf, 2.0/N * np.abs(yf[0:N/2]))
plt.grid()
plt.show()

这将创建如下内容:

fft out

我知道信号强度幅度的单位与其波形信号单位相同(V)。但我不明白FFT频率的幅度与原始信号幅度之间的关系。例如,50 Hz正弦波的幅度为5.0 V,那么为什么50 Hz的FFT幅度只有约3.6 V?
1个回答

6
在频域中的峰值幅度通常只有当音调的频率是FFT频率间隔1.0/(N*T)的整数倍时才与时间域中的音调幅度相匹配。当音调频率不是频率间隔的整数倍时,音调的能量会出现在多个bin上,这被称为Spectral leakage
在您具体的场景中,频率间隔为800/600 = 1.333Hz。相应地,80Hz的音调恰好是频率间隔的60倍,FFT显示的峰值与相关时间域分量的幅度相同1.0*np.sin(80.0 * 2.0*np.pi*x)。
另一方面,50Hz的音调对应着37.5倍的频率间隔。在这种情况下,能量分布在多个bin上,峰值相应减小,显示最大峰值为3.6而不是5.0 * np.sin(50.0 * 2.0*np.pi*x)时间域分量的完整5.0幅度。

我认为这很有道理。是否有一种方法可以从频域中的峰值幅度来确定时域中信号的振幅?比如,如果我正在使用一个我不知道其组成部分和振幅的信号,并想要弄清楚它们。 - TheStrangeQuark
1
在音调之间足够分散且没有太多干扰的假设下,您可以估计组件的幅度、频率和相位(参见我在stackoverflow上的另一个答案)。否则,当只有一个音调时,Parseval定理可能很方便。 - SleuthEye

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接