2012-02-26 182 views
32

我正在尋找如何把頻率軸在FFT(經由scipy.fftpack.fftfreq截取)轉換成頻率以赫茲,而不是箱或小數二進制位。SciPy的/ numpy的FFT頻率分析

我試圖以下代碼來測試出FFT:

t = scipy.linspace(0,120,4000) 
acc = lambda t: 10*scipy.sin(2*pi*2.0*t) + 5*scipy.sin(2*pi*8.0*t) + 2*scipy.random.random(len(t)) 

signal = acc(t) 

FFT = abs(scipy.fft(signal)) 
FFT = scipy.fftpack.fftshift(FFT) 
freqs = scipy.fftpack.fftfreq(signal.size) 

pylab.plot(freqs,FFT,'x') 
pylab.show() 

採樣速率應當是4000個樣本/120秒= 33.34樣本/秒。

該信號具有2.0赫茲信號,8.0 Hz的信號,和一些隨機噪聲。

我把FFT,抓住頻率,並繪製它。這些數字非常荒謬。如果我將頻率乘以33.34(採樣頻率),那麼我會在大約8 Hz和15 Hz處得到峯值,這似乎是錯誤的(也是頻率應該是4的因數,而不是2!)。

我在做什麼錯在這裏有什麼想法嗎?

回答

47

我覺得你不需要做fftshift(),並且可以通過採樣週期fftfreq():從圖

import scipy 
import scipy.fftpack 
import pylab 
from scipy import pi 
t = scipy.linspace(0,120,4000) 
acc = lambda t: 10*scipy.sin(2*pi*2.0*t) + 5*scipy.sin(2*pi*8.0*t) + 2*scipy.random.random(len(t)) 

signal = acc(t) 

FFT = abs(scipy.fft(signal)) 
freqs = scipy.fftpack.fftfreq(signal.size, t[1]-t[0]) 

pylab.subplot(211) 
pylab.plot(t, signal) 
pylab.subplot(212) 
pylab.plot(freqs,20*scipy.log10(FFT),'x') 
pylab.show() 

你可以看到有兩個高峯,在2Hz和8HZ。

enter image description here

+1

謝謝你這樣一個完整的答案。 hyry,爲什麼你選擇繪製20 * scipy.log10(FFT)而不是FFT? – Archie1986 2013-12-24 00:38:06

+0

HYRY爲您提供了一個以dB爲單位的Y軸圖,並且20log10爲幅度譜提供了正確的轉換。 – OldTinfoil 2014-05-15 16:06:20

6

每個bin的頻率寬度是(sampling_freq/num_bins)。

一個更根本的問題是,你的採樣率不足以感興趣的信號。您的採樣率爲8.3 Hz;您至少需要16Hz才能捕獲8Hz輸入音調。


1.所有的DSP專家;我意識到它實際上是BW相關的,而不是最大頻率。但我假設OP不想做欠採樣數據採集。

+0

我使用4000個樣本120秒 - 是不是33.3赫茲?這應該是綽綽有餘的,並且數字仍然關閉...... – 2012-02-26 19:53:43

+0

@asymptoticdesign:啊,好的。你的問題最初說1000.是的,這應該是足夠的。哪個bin索引是出現的能量? – 2012-02-26 19:59:24

-2

你的方程搞砸。

fs = 33.33 
df1 = 2*pi * (2.0/fs) 
df2 = 2*pi * (5.0/fs) 
x = [10*sin(n*df1) + 5*sin(n*df2) + 2*random.random() for n in range(4000)] 

這給你4000個樣本的函數,以33.33Hz採樣,代表120秒的數據。

現在把你的FFT。 Bin 0將保存DC結果。 Bin 1將爲33.33,bin 2將爲66.66等。

編輯:我忘記提及,由於您的採樣率爲33.33 Hz,可表示的最大頻率爲fs/2或16.665赫茲。

+2

-1:否。總帶寬爲33.33Hz,而不是每個垃圾箱的寬度。 – 2012-02-26 19:59:56