2011-07-18 153 views
64

我需要一些帮助来理解DFT/FFT计算的输出。理解FFT输出

我是一名经验丰富的软件工程师,需要解释一些智能手机加速计读数,例如查找主要频率。不幸的是,我十五年前就读过大部分大学EE课程,但过去几天我一直在阅读DFT和FFT(显然没有多大用处)。

请不要回答“走EE课”。我实际上打算这样做,如果我的雇主将支付我。 :)

因此,这里是我的问题:

我在32赫兹捕获的信号。这里是我在Excel中绘制的32分的1秒样本。

enter image description here

然后我得到了一些FFT code用Java编写的哥伦比亚大学(以下建议在后的“Reliable and fast FFT in Java”后)。

该程序的输出如下。我相信它正在运行一个就地FFT,所以它在输入和输出上都重复使用相同的缓冲区。

Before: 

Re: [0.887 1.645 2.005 1.069 1.069 0.69 1.046 1.847 0.808 0.617 0.792 1.384 1.782 0.925 0.751 0.858 0.915 1.006 0.985 0.97 1.075 1.183 1.408 1.575 1.556 1.282 1.06 1.061 1.283 1.701 1.101 0.702 ] 

Im: [0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ] 

After: 

Re: [37.054 1.774 -1.075 1.451 -0.653 -0.253 -1.686 -3.602 0.226 0.374 -0.194 -0.312 -1.432 0.429 0.709 -0.085 0.0090 -0.085 0.709 0.429 -1.432 -0.312 -0.194 0.374 0.226 -3.602 -1.686 -0.253 -0.653 1.451 -1.075 1.774 ] 

Im: [0.0 1.474 -0.238 -2.026 -0.22 -0.24 -5.009 -1.398 0.416 -1.251 -0.708 -0.713 0.851 1.882 0.379 0.021 0.0 -0.021 -0.379 -1.882 -0.851 0.713 0.708 1.251 -0.416 1.398 5.009 0.24 0.22 2.026 0.238 -1.474 ] 

所以,在这一点上,我不能做出正面或反面的输出。我理解DFT概念,例如实部是组件余弦波的幅度,虚部是组件正弦波的幅度。我也可以按照此图从伟大的书“The Scientist and Engineer's Guide to Digital Signal Processing”: enter image description here

所以我的具体问题是:

  1. 从FFT的输出,我怎么找到‘最发生频率’ ?这是我对加速度计数据分析的一部分。我应该读真实(余弦)还是虚构(正弦)数组?

  2. 我在时域有32点输入。 FFT的输出不应该是用于实数的16元素阵列和用于虚数的16元素阵列?为什么程序会给我32和32的实数和虚数阵列输出?

  3. 与前面的问题相关,我该如何解析输出数组中的索引?由于我输入了32个采样频率为32 Hz的样本,我的理解是,一个16元素的阵列输出应该使其指数均匀分布到1/2采样率(32 Hz),所以我理解每个元素数组表示(32 Hz * 1/2)/ 16 = 1 Hz?

  4. 为什么FFT输出值为负值?我认为这些值代表了正弦曲线的幅度。例如,对于频率为3的余弦波,Real [3] = -1.075的输出应该表示-1.075的振幅。对吗?幅度如何可能为负数?

+0

您想从加速计读数中计算什么:速度,距离?加速度计读数的噪声遵循高斯分布,我看不出正弦波如何适应这种情况。 – Ali

+0

应该删除java标记,因为它比通用语言更具通用性 – user3791372

回答

65
  1. 你不应该寻找复数的真实或想象部分(即你的真实和虚拟数组是什么)。相反,您需要查看定义为sqrt(real * real + imag * imag)的频率的大小。这个数字永远是积极的。现在你所要搜索的是最大值(忽略数组中的第一项),这是你的直流偏移,并且没有频率依赖信息。

  2. 因为您正在使用复数来复杂FFT,所以可以得到32个实数和32个虚数输出。请记住,您已将32个样本转换为64个值(或32个复数值),方法是将其扩展为零虚部。这导致频率结果出现两次的对称FFT输出。一旦准备好在输出0到N/2中使用,并且一次镜像到输出N/2到N.在你的情况下,简单地忽略输出N/2到N是最容易的。你不需要它们,它们是只是你如何计算FFT的一个神器。 (bin_id * freq/2)/(N/2)其中freq是您的采样频率(又称32 Hz,N是FFT的大小)。频率fft-bin方程式为(bin_id * freq/2)/在你的情况下,这可以简化为每个垃圾箱1 Hz。箱子N/2到N代表负频率(我知道奇怪的概念)。对于你的情况,它们不包含任何重要的信息,因为它们只是第一个N/2频率的镜像。

  3. 每个垃圾箱的实部和虚部形成一个复数。如果实部和虚部都是负数,而频率本身的幅度是正数,这是可以的(见我对问题1的回答)。我建议你阅读复数。解释它们是如何工作的(以及它们为什么有用)超过了在单个堆栈溢出问题中可以解释的内容。

注意:您可能还想要了解什么是自相关,以及如何使用它来查找信号的基频。我有一种感觉,这就是你真正想要的。

+0

谢谢。关于1:我看到了这个显示频谱的Matlab页面(http://www.mathworks.com/help/techdoc/ref/fft.html)。在该页面上是题为“y(t)的单边振幅谱”的图。是按照你的建议绘制频率的大小,sqrt(real^2 + img^2)?关于3:我仍然没有得到2Hz的每个bin结果。在我的情况下,N = 32和freq = 32,对吗?因此,有N/2 = 32/2 = 16个分档,最高频率(奈奎斯特)为freq/2 = 32/2 = 16 Hz,每16个分档产生16 Hz的频率, – stackoverflowuser2010

+0

是的,该图显示了光谱的强度 - | Y(f)|。绝对值条表示幅度。 Bin宽度=采样率/ FFT大小。你的采样率是32赫兹,你的FFT大小是32.是的,你是正确的箱宽! –

+0

修复仓频率。 –

4

1)除了第一个值(即DC分量)之外,查找真实数组中最高值的索引。您可能需要比32 Hz高得多的采样率和更大的窗口大小,才能获得有意义的结果。

2)两个阵列的后半部分是上半部分的镜像。例如,请注意,实数组(1.774)的最后一个元素与第二个元素(1.774)相同,并且虚数组(1.474)的最后一个元素是第二个元素的

3)您可以在32 Hz采样率下采集的最大频率为16 Hz(Nyquist limit),因此每个步骤为2 Hz。如前所述,请记住第一个元素是0 Hz(即DC偏移量)。

4)当然,负振幅是非常有意义的。这仅仅意味着信号被“翻转” - 标准FFT基于余弦,其在t = 0时通常具有值= 1,因此在时间= 0具有值= -1的信号将具有负幅度。

+0

感谢您的回复。 (1)你的意思是我可以忽略虚数(正弦)阵列,如果是这样,为什么?当然,正弦分量必须很重要? (2)为什么发生这种镜像?这仅仅是FFT算法的结果吗?大多数人会忽视镜像的一半吗? (3)你是如何计算2Hz的步幅的?我理解16Hz的奈奎斯特极限,所以如果有16个(非镜像)阵列元件,每个元件每个都必须是16Hz/16 = 1Hz? (4)为了找到主要频率,我只是把输出数组中的幅度值的绝对值? – stackoverflowuser2010

+0

您不应该在真实数组中查看最高值,并且不能忽略正弦/ I数组。相反,您需要复合复合矢量的大小。发生镜像是因为输入(I阵列)的一半全是零,所以结果只有一半的自由度。如果你的数据是真实的,你可以忽略它。 – hotpaw2

+0

是的,垃圾箱宽度是1赫兹。 –

7

您已经有了一些很好的答案,但我只是补充一点,您确实需要在FFT之前将window function应用于您的时域数据,否则会在您的频谱中出现令人讨厌的文物。

3

请注意,即使使用窗口功能,“最多发生的频率”也可能溅到多个FFT分档中。因此,您可能必须使用更长的窗口,多个窗口或插值来更好地估计任何谱峰的频率。