【问题标题】:Why do I obtain a skewed spectrum from the FFT? (Matlab)为什么我会从 FFT 获得倾斜的频谱? (Matlab)
【发布时间】:2016-02-17 19:11:52
【问题描述】:

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

编辑: 频谱似乎偏向低频。零填充只是使它可见:

为什么我的频谱偏斜?不应该是对称的吗?

【问题讨论】:

  • 我为指数 11、12、13、14 运行了您的代码,并得到了 max(power) 的以下索引:inds = p11: 5 p12: 9 p13: 16 p14: 32 这非常强烈地表明您正在丢失一个索引值。这应该是关于fft 为您做什么的有力线索。

标签: matlab fft


【解决方案1】:

TL;DR:使用更好的窗口函数!

长版:

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

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

顶部: 不加窗的频率响应:两个 delta 峰值,一个在正频率,一个在负频率。我总是绘制积极的部分,因为我没想到需要负频率分量。 中:矩形窗函数的频率响应。它相对较宽,但我不在乎,因为我认为我只有一个峰。 底部:补零信号的频率响应。在时域中,这是窗函数和正弦波的乘积。在频域中,这相当于窗函数的频率响应与完美正弦的频率响应的卷积。由于有两个峰值,窗口的相对较宽的频率响应显着重叠,导致频谱偏斜,因此峰值偏移。

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

【讨论】:

    【解决方案2】:

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

    当您进行零填充时,您会增加频率分辨率,尤其是在低端。

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

    如果您正在执行“正确的”fft,即从 -inf 到 +inf 进行积分,即使是那些低频分量也会为您提供 FFT 的零系数,但由于您正在执行有限求和,因此这些卷积的结果不为零,因此实际计算的傅立叶变换不准确。

    【讨论】:

    • 零填充添加低频分量听起来很合理。我想我什至可以看到,如果我看一下频谱,随着我添加零填充,它会变得越来越倾斜。
    • 知道如何规避这个问题吗?
    • 我做了更多的测试并意识到:频谱不会通过额外的零填充变得更加偏斜。它保持形状,采样越来越密集。
    • 并不是零填充增加了更多的低频分量,而是向 FFT 添加了更多的基函数,频率接近或低于低频信号,并且总和中的项不足以抵消贡献从这些。考虑一下:如果你有两个正弦,sin(x) 和 sin(x+dx),并将它们从 -inf 积分到 inf,它应该是零,但如果你计算一个有限的和或积分,它就不会是零。
    • 实际上有一种方法可以规避这一点:使用更多数据。您拥有的未填充数据越多,即计算频谱的段越长,低频功率估计就越准确将会。尝试例如Tmax=16*1024,你会发现现在你可以有更多的 bin 并且仍然是准确的。此外,对于大多数真实世界的数据,您不会遇到这种麻烦,这些数据不会是纯正弦曲线。
    【解决方案3】:

    这是您做错了什么(主要是分辨率问题)的图形说明。 编辑:这显示了每个 fft 数据点的功率,映射到 2^14 数据集的索引。也就是说,编号为 1,2,3 的 2^13 数据的索引映射到此图上的 1,3,5;编号为 1,2,3 的 2^12 数据的索引映射到 1,5,9;等等。

    。 您可以看到“真实”值实际上不应该是 512——您的索引偏离了 1 或 1 的一小部分。

    【讨论】:

    • 最好将一些低阶曲线(比如抛物线)拟合到最大值附近的几个点,并将拟合曲线的最大值作为输出。这样,fft 网格和您读取的输出之间没有耦合,并且您的分辨率不受现在的限制(因此您可以使用较少数量的零填充零)。
    • 感谢您的回答!这是一张不错的图片,但我不确定它是否支持您的结论:从图片中可以清楚地看到较低分辨率的峰值与较高分辨率的峰值不一致。这意味着具有无限分辨率的真正最大值不在生成频率处。
    • @Edgar 图表的要点是您没有足够的分辨率,即特定频率的数据点,无法将数据点标记为频谱的真实峰值。这就是为什么 Itamar 建议进行抛物线(或类似的)拟合以找到确切的峰值是一个好主意。
    • @CarlWitthoft 我同意这一点,这就是我更新问题的原因。事实上,频谱的最大值与生成信号的频率位于不同的位置(只要我添加零填充)。但是如果我添加更多的零,则插值会更好,但位置不再改变。
    猜你喜欢
    • 2013-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-09
    相关资源
    最近更新 更多