2011-07-18 185 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分檔中。因此,您可能必須使用更長的窗口,多個窗口或插值來更好地估計任何譜峯的頻率。