2016-08-05 33 views
1

Ich spiele mit Python und Scipy, um Windowing zu verstehen, machte ich ein Diagramm, um zu sehen, wie sich Windowing unter FFT verhält, aber das Ergebnis ist nicht, was ich sah. das Grundstück ist: enter image description hereSchlechte Ergebniszeichnung Fensterung FFT

die mittleren Plots sind reine FFT Grundstück, hier ist, wo ich komische Dinge bekommen. Dann habe ich die Triggerung geändert. Funktion Leck zu bekommen, einen 1 gerade für die 300 ersten Elemente des Arrays setzen, das Ergebnis: enter image description here

der Code:

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() 

EDIT: wie in den Kommentaren gefragt, i aufgetragen die Funktionen in dB-Skala, wodurch viel klarere Parzellen erhalten werden. Vielen Dank @SleuthEye! enter image description here

+0

Für die Liebe der Götter, bitte erkläre, was jede Box in der Handlung ist, was "reine FFT" bedeutet und was genau das Problem ist. –

+0

Was ist anders als erwartet? Die zweite Figur zeigt eine Spitze bei 0 von der DC-Komponente dieser eingefügten 1s. Was nicht direkt offensichtlich ist, ist das Leckniveau weit von den Spitzen. Sie würden das besser sehen, wenn Sie die Spektrumsamplituden auf einer logarithmischen Skala (Dezibel) zeigen würden. – SleuthEye

+0

@SleuthEye: das lineare Spektrum von der Sinuswelle und dem Fenster + Sünde scheint gut zu funktionieren, das Problem ist das mit der Hanning-Funktion, zeigt nichts genau, was ich sah, war etwa so: [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

Antwort

1

Es scheint, die Handlung, die problematisch ist die, erzeugt wird durch:

ax5.plot(fft_freq_axis,fft_hann) 

resultierende im Diagramm:

Initial problematic graph

statt des erwarteten graph from Wikipedia.

Es gibt eine Reihe von Problemen mit der Konstruktion des Plots. Der erste besteht darin, dass dieser Befehl im Wesentlichen versucht, ein komplexwertiges Array zu plotten (fft_hann). Sie können tatsächlich die Warnung ComplexWarning: Casting complex values to real discards the imaginary part als Ergebnis erhalten. Um einen Graphen zu erzeugen, die wie die von Wikipedia sieht, würde man die Größe nehmen müssen (anstelle des Realteils) mit:

ax5.plot(fft_freq_axis,abs(fft_hann)) 

Dann bemerken wir, dass es noch eine Linie durch unser Grundstück fällt. Mit Blick auf np.fft.fft's documentation:

Die Werte im Ergebnis folgt so genannten „Standard“ um: Wenn A = fft(a, n), dann A[0] enthält den Null-Frequenzterm (die Summe des Signals), die für echte immer rein real Eingaben. Dann enthält A[1:n/2] die Begriffe mit positiver Häufigkeit und A[n/2+1:] enthält die Begriffe mit negativer Häufigkeit in der Reihenfolge der abnehmend negativen Frequenz. [...] Die Routine np.fft.fftfreq(n) gibt ein Array zurück, das die Häufigkeiten der entsprechenden Elemente im Ausgang angibt.

der Tat, wenn wir die fft_freq_axis drucken können wir sehen, dass das Ergebnis:

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

, um dieses Problem zu bekommen wir müssen einfach nur die unteren und oberen Teile der Arrays mit np.fft.fftshift tauschen:

Dann sollten Sie beachten, dass das Diagramm auf Wikipedia tatsächlich mit Amplituden in decibels gezeigt wird.Sie würden dann mit dem gleichen tun müssen:

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

sollen wir dann werden immer näher, aber das Ergebnis ist nicht ganz dasselbe wie aus der folgenden Abbildung zu sehen:

Mostly fixed plot, missing side lobes

Dies liegt an der Tatsache, dass das Diagramm auf Wikipedia tatsächlich eine höhere Frequenzauflösung hat und den Wert des Frequenzspektrums erfasst, während es oszilliert, während Ihr Diagramm das Spektrum an weniger Punkten abtastet und viele dieser Punkte Amplituden nahe Null haben. Um dieses Problem zu lösen, müssen wir das Frequenzspektrum des Fensters an mehr Frequenzpunkten erhalten. Dies kann durch Zero-Padding der Eingabe in den FFT durchgeführt werden, oder einfach den Parameter n (gewünschte Länge des Ausgangs) auf einen Wert viel größer ist als die Eingangsgröße einstellen:

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

Sie können sich nicht vorstellen, wie dankbar ich bin !, ich schulde dir eine Schokolade !, das ist, was ich nicht verstehen konnte, vielen Dank! – tomzko