2016-08-05 106 views
1

即時通訊使用python和scipy來了解窗口,我做了一個情節,看看如何在FFT下的窗口行爲,但結果不是我所指出的。 的劇情是: enter image description here錯誤的結果繪製窗口FFT

中間的地塊是純FFT的情節,這裏是我得到奇怪的東西。 然後我改變了trig。函數獲取泄漏,把一個1個直數組的300個項時,結果是: enter image description here

代碼:

sign_freq=80 
sample_freq=3000 
num=np.linspace(0,1,num=sample_freq) 
i=0 
#wave data: 
sin=np.sin(2*pi*num*sign_freq)+np.sin(2*pi*num*sign_freq*2) 
while i<1000: 
    sin[i]=1 
    i=i+1 


#wave fft: 
fft_sin=np.fft.fft(sin) 
fft_freq_axis=np.fft.fftfreq(len(num),d=1/sample_freq) 

#wave Linear Spectrum (Rms) 
lin_spec=sqrt(2)*np.abs(np.fft.rfft(sin))/len(num) 
lin_spec_freq_axis=np.fft.rfftfreq(len(num),d=1/sample_freq) 

#window data: 
hann=np.hanning(len(num)) 

#window fft: 
fft_hann=np.fft.fft(hann) 

#window fft Linear Spectrum: 
wlin_spec=sqrt(2)*np.abs(np.fft.rfft(hann))/len(num) 

#window + sin 
wsin=hann*sin 

#window + sin fft: 
wsin_spec=sqrt(2)*np.abs(np.fft.rfft(wsin))/len(num) 
wsin_spec_freq_axis=np.fft.rfftfreq(len(num),d=1/sample_freq) 

fig=plt.figure() 
ax1 = fig.add_subplot(431) 
ax2 = fig.add_subplot(432) 
ax3 = fig.add_subplot(433) 
ax4 = fig.add_subplot(434) 
ax5 = fig.add_subplot(435) 
ax6 = fig.add_subplot(436) 
ax7 = fig.add_subplot(413) 
ax8 = fig.add_subplot(414) 

ax1.plot(num,sin,'r') 
ax2.plot(fft_freq_axis,abs(fft_sin),'r') 
ax3.plot(lin_spec_freq_axis,lin_spec,'r') 
ax4.plot(num,hann,'b') 
ax5.plot(fft_freq_axis,fft_hann) 
ax6.plot(lin_spec_freq_axis,wlin_spec) 
ax7.plot(num,wsin,'c') 
ax8.plot(wsin_spec_freq_axis,wsin_spec) 

plt.show() 

編輯:如要求在評論,我繪製的以dB爲單位的函數,獲得更清晰的圖。非常感謝@SleuthEye! enter image description here

+0

對於神的愛,請解釋劇情中的每一個盒子是什麼,「純粹的FFT」意味着什麼,問題到底是什麼。 –

+0

與您的預期有什麼不同?第二張圖顯示了插入1的直流分量的0處的峯值。不直接明顯的是遠離峯值的泄漏水平。如果以對數刻度(分貝)顯示頻譜幅度,則會更好。 – SleuthEye

+0

@SleuthEye:來自正弦波和窗口+ sin的線性光譜似乎工作正常,問題是具有漢寧函數的問題,沒有顯示任何精確的,我猜測是這樣的:[link](https:/ /upload.wikimedia.org/wikipedia/commons/thumb/b/b3/Window_function_and_frequency_response_-_Hann.svg/500px-Window_function_and_frequency_response_-_Hann.svg.png).Greets! :) – tomzko

回答

1

看來這是有問題的情節是一個通過生成:

ax5.plot(fft_freq_axis,fft_hann) 

導致圖:

Initial problematic graph

而不是預期的graph from Wikipedia

情節的構建方式有很多問題。第一個是這個命令本質上是試圖繪製一個複數值數組(fft_hann)。結果你實際上可能會收到警告ComplexWarning: Casting complex values to real discards the imaginary part。爲了產生它看起來像從維基百科的一個圖表,你將不得不採取的大小(而非實部)與:

ax5.plot(fft_freq_axis,abs(fft_hann)) 

然後,我們注意到,仍有通過我們的情節驚人的一條線。縱觀np.fft.fft's documentation:在結果

值遵循所謂的「標準」的順序:如果A = fft(a, n),然後A[0]包含零頻率項(信號之和),這始終是真正的純實投入。然後A[1:n/2]包含正頻率項,而A[n/2+1:]包含負頻率項,按負頻率遞減的順序。 [...] 例程np.fft.fftfreq(n)返回一個數組,給出輸出中相應元素的頻率。

事實上,如果我們打印fft_freq_axis,我們可以看到的結果是:

[ 0. 1. 2. ..., -3. -2. -1.] 

爲了解決這個問題,我們只需用np.fft.fftshift交換陣列的上,下部分:

ax5.plot(np.fft.fftshift(fft_freq_axis),np.fft.fftshift(abs(fft_hann))) 

然後您應該注意維基百科上的圖形實際上顯示的幅度爲decibels。然後,您需要做相同的:

ax5.plot(np.fft.fftshift(fft_freq_axis),np.fft.fftshift(20*np.log10(abs(fft_hann)))) 

我們應該然後越來越近,但結果不太一樣可以從下面的圖中可以看出:

Mostly fixed plot, missing side lobes

這是因爲維基百科上的圖實際上具有較高的頻率分辨率,並在頻譜振盪時捕獲頻譜的值,而您的圖以較少的點對頻譜進行採樣,並且很多這些點的振幅接近零。爲了解決這個問題,我們需要在更多的頻率點獲得窗口的頻譜。 這可以通過零填充的輸入來完成的FFT,或者更簡單地設定參數n(輸出的期望長度)的值比輸入尺寸大得多:

N = 8*len(num) 
fft_freq_axis=np.fft.fftfreq(N,d=1/sample_freq) 
fft_hann=np.fft.fft(hann, N) 
ax5.plot(np.fft.fftshift(fft_freq_axis),np.fft.fftshift(20*np.log10(abs(fft_hann)))) 
ax5.set_xlim([-40, 40]) 
ax5.set_ylim([-50, 80]) 

Final plot

+0

你無法想象我是多麼的高興!,我欠你一顆巧克力!,這是我無法理解的,非常感謝! – tomzko