2017-06-21 3 views
0

I ein Matlab-Skript haben die DFT eines Signals und plotten es zu berechnen:FFT-Ergebnisse Matlab VS Numpy (Python): nicht die gleichen Ergebnisse

(data here gefunden werden kann)

clc; clear; close all; 

fid = fopen('s.txt'); 
txt = textscan(fid,'%f'); 

s = cell2mat(txt); 

nFFT = 100; 
fs = 24000; 
deltaF = fs/nFFT; 
FFFT = [0:nFFT/2-1]*deltaF; 
win = hann(length(s)); 

sw = s.*win; 
FFT = fft(sw, nFFT)/length(s); 
FFT = [FFT(1); 2*FFT(2:nFFT/2)]; 
absFFT = 20*log10(abs(FFT)); 

plot(FFFT, absFFT) 
grid on 

Ich versuche es in Python zu übersetzen und bekomme nicht das gleiche Ergebnis.

import numpy as np 
from matplotlib import pyplot as pl 

x = np.genfromtxt("s.txt", delimiter=' ') 

nfft = 100 
fs = 24000 
deltaF = fs/nfft; 
ffft = [n * deltaF for n in range(nfft/2-1)] 
ffft = np.array(ffft) 
window = np.hanning(len(x)) 

xw = np.multiply(x, window) 
fft = np.fft.fft(xw, nfft)/len(x) 
fft = fft[0]+ [2*fft[1:nfft/2]] 
fftabs = 20*np.log10(np.absolute(fft)) 

pl.figure() 
pl.plot(ffft, np.transpose(fftabs)) 
pl.grid() 

Die Plots I (Matlab auf der linken Seite, Pyhton auf der rechten Seite) erhalten:

enter image description here

Was mache ich falsch?

+0

Vielleicht nicht Ihr Hauptproblem, aber Ihre Fensterfunktion sollte die gleiche Größe wie die FFT haben, d. H. Nfft, nicht len ​​(x) (gilt sowohl für MATLAB als auch für Python-Code). –

+0

@Paul R Interessant, wo kann ich mehr Informationen darüber finden? – hibol

+0

Hier auf StackOverflow gibt es einige Fragen und Antworten, die Fensterfunktionen und FFTs abdecken. Die Quintessenz ist jedoch, dass Sie eine [Fensterfunktion] (https://en.wikipedia.org/wiki/Window_function) auf die Eingabedaten einer FFT anwenden, um [spektrales Lecken] zu reduzieren (https: // en. wikipedia.org/wiki/Spectral_leakage). Die Größe dieser Fensterfunktion muss daher der Größe der FFT entsprechen. –

Antwort

3

Beiden Codes unterscheiden sich in einem Fall, dass Sie zwei Listen

FFT = [FFT(1); 2*FFT(2:nFFT/2)]; 

in dem MATLAB-Code

in den anderen verketten Sie den ersten Wert von fft mit dem Rest des

fft = fft[0]+ [2*fft[1:nfft/2]] 

Vektor hinzufügen

'+' nicht verketten hier, weil Sie numpy Array haben

I n Python, sollte es sein:

fft = fft[0:nfft/2] 
fft[1:nfft/2] = 2*fft[1:nfft/2] 
0

Ich bin kein Mathlab-Benutzer, also bin ich mir nicht sicher, aber es gibt ein paar Dinge, die ich fragen würde, ob ich Ihnen helfen kann.

Sie haben np.array aufgerufen, nachdem Array erstellt wurde (ffft). Das wird wahrscheinlich nicht die Art der Array ändern, wie Sie es erhofft haben, vielleicht wäre es besser zu versuchen, es innerhalb np.array(n * deltaF for n in range(nfft/2-1)) zu definieren Ich bin mir nicht sicher, die Formatierung, aber Sie bekommen die Idee. Die andere Sache ist, dass die Bandbreite für mich nicht richtig erscheint. Sie möchten, dass es einen Wert von 49 hat?

Eine andere ist die fft = fft[0]+ [2*fft[1:nfft/2]] im Vergleich zu FFT = [FFT(1); 2*FFT(2:nFFT/2)]; Ich bin mir nicht sicher, ob der Vergleich genau ist oder nicht. Es schien mir nur eine andere Art von Definition zu sein.

Auch wenn ich diese Art von Berechnungen mache, drucke ich die Zwischenschritte aus, damit ich die Zahlen vergleichen kann, um zu sehen, wo sie bricht.

Hoffe, das hilft.

+0

Danke. Ich habe die Definition von ffft so geändert: 'ffft = np.array (n * deltaF für n im Bereich (nfft/2-1))'. Nicht sicher über den zweiten Teil des Codes, den Sie erwähnen. Ich habe eine Lösung gefunden und werde sie unten veröffentlichen. Und ich kümmere mich nicht wirklich um die Anzahl der Punkte, die ich bekomme. Ich werde wahrscheinlich einige Tests mit verschiedenen Werten machen. – hibol

0

Ich fand heraus, dass die Verwendung von np.fft.rfft statt np.fft.fft und Ändern Sie den Code wie folgt macht den Job:

import numpy as np 
from matplotlib import pyplot as pl 

x = np.genfromtxt("../Matlab/s.txt", delimiter=' ') 

nfft = 100 
fs = 24000 
deltaF = fs/nfft; 
ffft = np.array([n * deltaF for n in range(nfft/2+1)]) 
window = np.hanning(len(x)) 

xw = np.multiply(x, window) 
fft = np.fft.rfft(xw, nfft)/len(x) 
fftabs = 20*np.log10(np.absolute(fft)) 

pl.figure() 
pl.plot(np.transpose(ffft), fftabs) 
pl.grid() 

Das resultierende Grundstück: right result with Python

Ich kann sehen, dass der erste und der letzte Punkt sowie die Amplituden nicht gleich sind. Es ist kein Problem für mich (ich interessiere mich mehr für die allgemeine Form), aber wenn jemand es erklären könnte, wäre ich glücklich.

Verwandte Themen