Python 我怎样才能得到我的FFT峰值,正好在我信号的频率上?

Python 我怎样才能得到我的FFT峰值,正好在我信号的频率上?,python,numpy,scipy,fft,Python,Numpy,Scipy,Fft,我在这里看到了下面的代码,但如果你绘制它并放大它,频率峰值并不完全在50Hz和80Hz;他们有点不对劲。有人知道为什么会这样吗?如何使峰值精确为50Hz和80Hz import numpy as np import matplotlib.pyplot as plt import scipy.fftpack # Number of samplepoints N = 600 # sample spacing T = 1.0 / 800.0 x = np.linspace(0.0, N*T, N)

我在这里看到了下面的代码,但如果你绘制它并放大它,频率峰值并不完全在50Hz和80Hz;他们有点不对劲。有人知道为什么会这样吗?如何使峰值精确为50Hz和80Hz

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

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

fig, ax = plt.subplots()
ax.plot(xf, 2.0/N * np.abs(yf[:N//2]))
plt.show()


这是一个简单的近似错误,因为
xf
没有假定值
50
和/或
80
。如果更改
N
和/或
linspace()
参数,则可以使
xf
精确地在
50
80
处采样,并且没有看到峰值位移:

将numpy导入为np
将matplotlib.pyplot作为plt导入
导入scipy.fftpack
#采样点数量
N=80
#样本间距
T=1.0/800.0
x=np.linspace(0.0,N*T,N)
y=np.sin(50.0*2.0*np.pi*x)+0.5*np.sin(80.0*2.0*np.pi*x)
yf=scipy.fftpack.fft(y)
xf=np.linspace(0.0,1.0/(2.0*T),N//2+1)
图,ax=plt.子批次(图尺寸=(10,10))
ax.plot(xf,2.0/N*np.abs(yf[:N//2+1]))
ax.绘图([50,50],[0,1])
ax.绘图([80,80],[0,1])
plt.show()

使用
xf

[  0.  10.  20.  30.  40.  50.  60.  70.  80.  90. 100. 110. 120. 130.
 140. 150. 160. 170. 180. 190. 200. 210. 220. 230. 240. 250. 260. 270.
 280. 290. 300. 310. 320. 330. 340. 350. 360. 370. 380. 390. 400.]

如果正弦波在FFTs长度内为整数周期,则纯未调制正弦波的频率仅显示为单个FFT bin峰值结果

否则,如果频率与FFT的周期基向量稍有不同,则会出现加窗伪影,有时称为“泄漏”


如果您希望非插值FFT峰值幅值正好与信号频率一致,则必须将FFT长度更改为信号周期的整数倍(或更改信号频率)。

尽管这已经是一个例外答案:

如果一个人需要知道一个峰值的精确频率,有一些简单的方法不需要尝试调整采样率。如果你不知道你想要测量的频率,你会怎么做。所以这不是显示问题的答案,而是“现实生活”中的检测问题。假设其他峰值“很远”,有一个简单的方法,使用高斯窗口。在对数尺度上,峰值将具有抛物线形状,因此三个最高点正好提供最大值的真实位置。这可以转化为一个简单的程序,只求解一个线性方程。这是用于分析光谱的I类的一部分:

    def get_base_frequency( self ):
        """
        uses the fact that the fourier of a gaussion is a gaussian.
        folding the virtual deltapeak of a frequency results in a gaussian.
        taking the log and looking at two consecutive bins, preferably near the maximum, 
        allows to calculate the position of the maximum, i.e. the frequency
        (square terms of the gaussians cancel and a linear equation is solved)
        """
        sigma = self.wavePoints / 8.0 ##my choice ... seems to work well
        tau = self.wavePoints / ( 2.0 * np.pi * sigma )
        pf, ps = self.spectrum_single_sided( windowType=[ 'Gaussian', sigma ] )
        ### fft providing freqency and spectral data
        n = np.argmax( ps ) - 1
        slg = tau**2 * np.log( ps[ n + 1 ] / ps[ n ] )
        better = slg + n + 0.5
        return better * self.sampleRate / self.wavePoints
就这样


如果需要峰值高度,我建议使用平顶窗口进行第二次fft。

上面的图是
N=600
?是的,上面的图是针对代码的