我尝试用Matlab找到最强的频率成分。它可以工作,但是如果数据点和周期没有很好地对齐,我需要对数据进行零填充以增加FFT分辨率。到目前为止一切都很好。
问题在于,当我进行零填充时,具有最大功率的频率会发生变化,即使所有内容都很好地对齐,我也希望得到清晰的结果。
这是我的MWE:
Tmax = 1024;
resolution = 1024;
period = 512;
X = linspace(0,Tmax,resolution);
Y = sin(2*pi*X/period);
% N_fft = 2^12; % still fine, max_period is 512
N_fft = 2^13; % now max_period is 546.1333
F = fft(Y,N_fft);
power = abs(F(1:N_fft/2)).^2;
dt = Tmax/resolution;
freq = (0:N_fft/2-1)/N_fft/dt;
[~, ind] = max(power);
max_period = 1/freq(ind)
零填充最多2^12
一切正常,但当我将其填充到2^13
时,我得到了错误的结果。似乎太多零填充会改变光谱,但我对此表示怀疑。我宁愿期待我的代码中的错误,但我找不到它。我做错了什么?
编辑:看起来光谱偏向低频。零填充只会使其可见:
为什么我的频谱会出现偏差?它不应该是对称的吗?
答案 0 :(得分:2)
以下是您所做错事的图解说明(主要是解决问题)。 编辑:这显示每个fft数据点的功率,映射到2 ^ 14数据集的索引。也就是说,在该图上,编号为1,2,3的2 ^ 13数据的索引映射到1,3,5; 2 ^ 12数据的索引编号1,2,3映射到1,5,9;等等。
答案 1 :(得分:2)
它不是代码中的错误。它与DFT的属性有关(因此也就是FFT,它只是DFT的快速版本)。
当您使用零填充时,您可以添加频率分辨率,尤其是在低端。
这里使用正弦波作为测试,因此您基本上使用有限正弦和余弦(参见此处https://en.wikipedia.org/wiki/Fast_Fourier_transform详细信息)对有限长度正弦进行卷积,其频率几乎相同或更低。
如果你正在做一个正确的" fft,即从-inf到+ inf进行积分,即使那些低频分量也会给你零FFT系数,但由于你正在进行有限和,这些卷积的结果不是零,因此实际计算的傅立叶变换是不准确的。
答案 2 :(得分:0)
TL; DR:使用更好的窗口功能!
长版:
经过进一步搜索,我终于找到了解释。既不是索引问题,也不是零填充添加的额外低频分量。矩形窗口的频率响应与负频率分量相结合是罪魁祸首。我发现了this website解释窗口函数。
我做了更多的情节来解释:
顶部:没有窗口的频率响应:两个 delta峰值,一个在正极,一个在负频率。我总是绘制正面部分,因为我并不期望需要负频率成分。 中:矩形窗函数的频率响应。它相对宽泛,但我并不关心,因为我认为我只有一个峰值。 底部:零填充信号的频率响应。在时域中,这是窗函数和正弦波的乘法。在频域中,这相当于窗函数的频率响应与完美正弦的频率响应的卷积。由于存在两个峰值,因此窗口的相对较宽的频率响应显着重叠,从而导致光谱偏斜,从而产生偏移的峰值。
解决方案:避免这种情况的一种方法是使用适当的窗口函数(如汉明窗口),使窗口的频率响应小得多,从而减少重叠。