为什么我从FFT获得偏斜的光谱? (Matlab的)

时间:2015-11-16 16:01:58

标签: matlab fft

我尝试用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时,我得到了错误的结果。似乎太多零填充会改变光谱,但我对此表示怀疑。我宁愿期待我的代码中的错误,但我找不到它。我做错了什么?

编辑:看起来光谱偏向低频。零填充只会使其可见:

为什么我的频谱会出现偏差?它不应该是对称的吗?

skewed spectrum

3 个答案:

答案 0 :(得分:2)

以下是您所做错事的图解说明(主要是解决问题)。 编辑:这显示每个fft数据点的功率,映射到2 ^ 14数据集的索引。也就是说,在该图上,编号为1,2,3的2 ^ 13数据的索引映射到1,3,5; 2 ^ 12数据的索引编号1,2,3映射到1,5,9;等等。

power curves vs. padding。 您可以看到“真实”值实际上不应该是512 - 您的索引关闭1或1的一小部分。

答案 1 :(得分:2)

它不是代码中的错误。它与DFT的属性有关(因此也就是FFT,它只是DFT的快速版本)。

当您使用零填充时,您可以添加频率分辨率,尤其是在低端。

这里使用正弦波作为测试,因此您基本上使用有限正弦和余弦(参见此处https://en.wikipedia.org/wiki/Fast_Fourier_transform详细信息)对有限长度正弦进行卷积,其频率几乎相同或更低。

如果你正在做一个正确的" fft,即从-inf到+ inf进行积分,即使那些低频分量也会给你零FFT系数,但由于你正在进行有限和,这些卷积的结果不是零,因此实际计算的傅立叶变换是不准确的。

答案 2 :(得分:0)

TL; DR:使用更好的窗口功能!

长版:

经过进一步搜索,我终于找到了解释。既不是索引问题,也不是零填充添加的额外低频分量。矩形窗口的频率响应与频率分量相结合是罪魁祸首。我发现了this website解释窗口函数。

我做了更多的情节来解释:

solution to my FFT issue

顶部:没有窗口的频率响应:两个 delta峰值,一个在正极,一个在负频率。我总是绘制正面部分,因为我并不期望需要负频率成分。 中:矩形窗函数的频率响应。它相对宽泛,但我并不关心,因为我认为我只有一个峰值。 底部:零填充信号的频率响应。在时域中,这是窗函数和正弦波的乘法。在频域中,这相当于窗函数的频率响应与完美正弦的频率响应的卷积。由于存在两个峰值,因此窗口的相对较宽的频率响应显着重叠,从而导致光谱偏斜,从而产生偏移的峰值。

解决方案:避免这种情况的一种方法是使用适当的窗口函数(如汉明窗口),使窗口的频率响应小得多,从而减少重叠。