Ich bin neu im Prinzip der Berechnung der Momentanfrequenz und habe viele Fragen dazu gestellt. Sie finden sie alle in einer Aufzählungsliste am Ende dieses Textes. Der Text mag etwas lang sein, entschuldigen Sie das, aber ich habe wirklich versucht, dieses Problem selbst zu lösen.
Ich interessiere mich also für die Momentanfrequenz eines reellen Signals . Die Berechnung erfolgt mit Hilfe eines analytischen Signals , wobei die Hilbert-Transformation von .
Um die Momentanfrequenzen aus dem analytischen Signal zu berechnen, folgte ich dem Papier:
Die Berechnung der Momentanfrequenz und der Momentanbandbreite durch Arthur E. Barns aus dem Jahr 1992. In diesem Artikel stellt er mehrere Methoden zur Berechnung der Momentanfrequenz vor. Ich schreibe alle Formeln auf, die er in einem Moment vorgeschlagen (und verwendet) hat.
Zum "Lernen" habe ich in MATLAB mit einem sehr einfachen und zwei etwas komplexeren Signalen herumgespielt und wollte ihre momentanen Frequenzen erhalten.
Fs = 1000; % sampling-rate = 1kHz
t = 0:1/Fs:10-1/Fs; % 10s 'Timevector'
chirp_signal = chirp(t,0,1,2); % 10s long chirp-signal, signal 1
added_sinusoid = chirp_signal + sin(2*pi*t*10); % chirp + sin(10Hz), signal 2
modulated_sinusoid = chirp_signal .* sin(2*pi*t*10); % chirp * sin(10Hz), signal 3
Die Diagramme im Zeitbereich dieser drei Signale sehen wie folgt aus:
Die Diagramme aller Momentanfrequenzen, die ich nach Anwendung aller Methoden aus dem Papier erhalten habe, sind folgende:
Momentanfrequenzen des reinen Chirpsignals: Momentanfrequenzen des Chirpsignals mit hinzugefügtem Sinus: Momentanfrequenzen des modulierten Chirpsignals: Bitte beachten Sie, dass in allen drei Bildern die y-Achse von Diagramm 3 und 4 vergrößert ist, also die Amplituden dieser Signale sind sehr klein!
Die erste Möglichkeit, vom analytischen Signal zur momentanen Frequenz zu gelangen, ist:
wobei die momentane Phase ist. Ich denke, dies ist die heute am häufigsten verwendete Methode, zumindest auf der MATLAB-Webseite wird sie so berechnet. Der Code sieht folgendermaßen aus:
function [instantaneous_frequency] = f2(analytic_signal,Fs)
factor = Fs/(2*pi);
instantaneous_frequency = factor * diff(unwrap(angle(analytic_signal)));
% Insert leading 0 in return-vector to maintain size
instantaneous_frequency = [0 instantaneous_frequency];
end
In der Arbeit schlagen Scheunen nun vier andere Möglichkeiten vor (oder besser gesagt die Zusammenstellungen), um Momentanfrequenzen aus dem analytischen Signal zu berechnen. Er erwähnt auch die obere Formel, ist jedoch der Meinung, dass sie aufgrund von Unklarheiten in der Phase unpraktisch ist. Ich denke, er kannte die unwrap()
Methode nicht, genauer gesagt die Mathematik dahinter. (Ich selbst habe diese Methode erst heute kennengelernt, als ich mir einige andere Quellcodes auf Momentanfrequenzen angesehen habe.)
In seiner Arbeit hat die Formel die Bezeichnung Nummer (2), daher habe ich dem f (t) den Index 2 gegeben. Alle anderen Indizes entsprechen auf die gleiche Weise ihren Zahlen in der Arbeit.
Wegen der Unklarheiten in der Phase schlägt er eher vor:
function [instantaneous_frequency] = f3(analytic_signal,Fs,T)
x = real(analytic_signal);
y = imag(analytic_signal);
diff_x = diff(x);
diff_y = diff(y);
factor = Fs/(2*pi);
a = x(2:end).*diff_y;
b = y(2:end).*diff_x;
c = x(2:end).^2;
d = y(2:end).^2;
instantaneous_frequency = factor * ((a-b)./(c+d));
% Insert leading 0 in return-vector to maintain size
instantaneous_frequency = [0 instantaneous_frequency];
end
Dann gibt Barner drei weitere Formeln an, die er "Momentanfrequenznäherungen" nennt:
function[instantaneous_frequency] = f9(analytic_signal, Fs, T)
x = real(analytic_signal);
y = imag(analytic_signal);
factor = Fs/(2*pi*T);
a = x(1:end-T).*y(1+T:end);
b = x(1+T:end).*y(1:end-T);
c = x(1:end-T).*x(1+T:end);
d = y(1:end-T).*y(1+T:end);
instantaneous_frequency = factor.*atan((a-b)./(c+d));
% Append 0 to return-vector to maintain size
instantaneous_frequency = [instantaneous_frequency zeros(1,T)];
end
function [instantaneous_frequency] = f11(analytic_signal, Fs, T)
x = real(analytic_signal);
y = imag(analytic_signal);
factor = Fs/(4*pi*T);
a = x(1:end-2*T).*y(1+2*T:end);
b = x(1+2*T:end).*y(1:end-2*T);
c = x(1:end-2*T).*x(1+2*T:end);
d = y(1:end-2*T).*y(1+2*T:end);
instantaneous_frequency = factor.*atan((a-b)./(c+d));
% Append and insert 0s to maintain size
instantaneous_frequency = [zeros(1,T) instantaneous_frequency zeros(1,T)];
end
function [instantaneous_frequency] = formula14(analytic_signal, Fs, T);
x = real(analytic_signal);
y = imag(analytic_signal);
factor = 2*Fs/(pi*T);
a = x(1:end-T).*y(1+T:end);
b = x(1+T:end).*y(1:end-T);
c = (x(1:end-T)+x(1+T:end)).^2;
d = (y(1:end-T)+y(1+T:end)).^2;
instantaneous_frequency = factor * ((a-b)./(c+d));
% Append and insert 0s to maintain size
instantaneous_frequency = [instantaneous_frequency zeros(1,T)];
end
In allen 3 Näherungsformeln wurde T auf Fs gesetzt (T = Fs = 1000 = 1s), wie in der Veröffentlichung vorgeschlagen.
Jetzt sind meine Fragen:
- Die Formeln f2 und f3 geben das gleiche Ergebnis für das reine Chirpsignal zurück. Ich finde das gut, da sie das gleiche berechnen. Die drei Approximationsmethoden geben nicht dasselbe zurück, nicht einmal etwas, das nahe daran liegt! Warum ist das so? (Ich hoffe es ist nicht nur ein Programmierfehler ...)
- Obwohl sie das Gleiche zurückgeben, fangen sie vor allem am Ende der Handlung an, viel zu wackeln . Was ist die Erklärung dafür? Ich habe zuerst an so etwas wie Aliasing gedacht, aber meine Abtastfrequenz ist im Vergleich zur Frequenz der Signale ziemlich hoch, daher denke ich, dass dies ausgeschlossen werden kann.
Zumindest f2 und f3 scheinen bei einem reinen Chirpsignal angemessen zu funktionieren, aber alle Methoden, einschließlich f2 und f3, scheinen schrecklich zu scheitern, wenn es um mehr als eine Frequenz im Signal geht. In der Realität ist es eher immer der Fall, mehr als eine Frequenz in einem Signal zu haben. Wie kann man also die (mehr oder weniger) korrekte Momentanfrequenz erhalten?
- Ich weiß eigentlich gar nicht, was mich erwartet, wenn mehr als eine Frequenz im Signal vorhanden ist. Die Berechnung gibt eine Zahl für einen bestimmten Zeitpunkt zurück. Was ist also zu tun, wenn wie hier mehr Frequenzen vorhanden sind? Den Durchschnitt aller Frequenzen zurückgeben oder so?
Und meine wahrscheinlich wichtigste Frage ist, wie das in einer echten und ausgearbeiteten Software gehandhabt wird. Nehmen wir an, ich möchte die momentane Frequenz des modulierten Signals bei 1,75 s wissen und habe die Methode f2 gewählt, dann kann ich Glück haben und eine Zahl nahe 6 [Hz] erhalten, was höchstwahrscheinlich die richtige Antwort ist, oder ich Wähle meine Ergebnisse ein paar Proben daneben und plötzlich bekomme ich ein verdrahtetes, viel zu hohes Ergebnis, weil ich leider einen Wert in der Spitze ausgewählt habe. Wie kann damit umgegangen werden? Durch Nachbearbeitung mit Mittelwert oder noch besser einem Medianfilter? Ich denke sogar, dass dies sehr schwierig werden könnte, insbesondere in Regionen, in denen viele Stacheln nebeneinander liegen.
Und eine letzte, nicht so wichtige Frage, warum die meisten Artikel, die ich über Momentanfrequenzen finde, aus dem Bereich der Geographie stammen, insbesondere bei der Berechnung seismographischer Ereignisse wie Erdbeben. Auch Barnes Artikel nimmt dies als Beispiel. Ist die momentane Frequenz nicht in vielen Bereichen interessant?
Bis jetzt bin ich sehr dankbar für jede Antwort, besonders wenn mir jemand Tipps gibt, wie man sie in ein echtes Softwareprojekt implementiert ;)
Herzliche Grüße, Patrick