我正在尝试使用快速傅立叶变换来提取单个正弦函数的相移。我知道在纸上,如果我们表示将函数转换为T,则我们具有以下关系:
但是,我发现虽然我能够准确捕获余弦波的频率,但是除非我以极高的速率采样,否则相位是不准确的。例如:
import numpy as np
import pylab as pl
num_t = 100000
t = np.linspace(0,1,num_t)
dt = 1.0/num_t
w = 2.0*np.pi*30.0
phase = np.pi/2.0
amp = np.fft.rfft(np.cos(w*t+phase))
freqs = np.fft.rfftfreq(t.shape[-1],dt)
print (np.arctan2(amp.imag,amp.real))[30]
pl.subplot(211)
pl.plot(freqs[:60],np.sqrt(amp.real**2+amp.imag**2)[:60])
pl.subplot(212)
pl.plot(freqs[:60],(np.arctan2(amp.imag,amp.real))[:60])
pl.show()
使用num = 100000点,我得到的相位为1.57173880459。使用num = 10000点,我得到的相位为1.58022110476。
使用num = 1000点,我得到1.6650441064的相位。
怎么了即使有1000点,我每个周期也有33点,这足以解决它。有没有办法增加计算的频率点的数量?有什么办法可以减少点数吗?
编辑:从进一步的实验看来,我每个周期需要约1000个点才能准确地提取一个相位。为什么?!
编辑2:进一步的实验表明,准确性与每个周期的点数有关,而不是绝对数。增加每个周期的采样点数可以使相位更准确,但是如果信号频率和采样点数都增加相同的倍数,则精度将保持不变。
最佳答案
您的点在整个间隔内分布不均,结尾的点加倍:0
与1
是同一点。显然,您获得的分数越多,重要性就越不重要,但仍然会出现一些错误。您可以完全避免它,linspace
为此有一个标志。它还具有一个标志,可以直接将dt
与数组一起返回。
做
t, dt = np.linspace(0, 1, num_t, endpoint=False, retstep=True)
代替
t = np.linspace(0,1,num_t)
dt = 1.0/num_t
然后就可以了:)