Sono nuovo del principio del calcolo della frequenza istantanea e ho formulato molte domande al riguardo. Li trovi tutti in un elenco di punti elenco alla fine di questo testo. Il testo potrebbe essere un po 'lungo, mi scusi per quello, ma ho davvero cercato di risolvere il problema da solo.
Quindi sono interessato alla frequenza istantanea di un segnale con valore reale . Il calcolo viene eseguito con l'aiuto di un segnale analitico , dove è la trasformazione di Hilbert di .
Per calcolare le frequenze istantanee dal segnale analitico ho seguito il documento:
Il calcolo della frequenza istantanea e della larghezza di banda istantanea di Arthur E. Barns dal 1992. In questo articolo introduce diversi metodi per calcolare la frequenza istantanea. Scrivo, tutte le formule che ha proposto (e che ho usato) in un momento.
Per "apprendere", ho giocato con un segnale molto semplice e due segnali un po 'più complessi, in MATLAB, e volevo ottenere le loro frequenze istantanee.
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
I grafici nel dominio del tempo di questi tre segnali sono i seguenti:
I grafici di tutte le frequenze istantanee che ho ottenuto dopo aver applicato tutti i metodi dal documento, sono i seguenti:
Frequenze istantanee di segnale chirp puro: Frequenze istantanee di segnale chirp con sinusoide aggiunta: Frequenze istantanee di segnale chirp modulato: Si noti che in tutte e tre le immagini, l'asse y del diagramma 3 e 4 viene ingrandito, quindi le ampiezze di quelle i segnali sono molto piccoli!
La prima possibilità di passare dal segnale analitico alla frequenza istantanea è:
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
Nell'articolo Barns ora suggerisce (o meglio ha detto di compilare) altri quattro modi per calcolare le frequenze istantanee dal segnale analitico. Cita anche la formula superiore, ma è dell'opinione che sia poco pratica a causa delle ambiguità nella fase. Immagino che non conoscesse il unwrap()
metodo o, per essere più precisi, la matematica dietro di esso. (Io stesso ho imparato a conoscere quel metodo proprio oggi, guardando alcuni altri codici sorgente su frequenze istantanee)
Nel suo articolo, la formula ha l'etichetta Numero (2), quindi ho dato a f (t) l'indice 2. Tutti gli altri indici corrispondono allo stesso modo ai loro numeri nel documento.
A causa delle ambiguità in fase, suggerisce piuttosto:
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
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 tutte e 3 le formule di approssimazione T è stato impostato su Fs (T = Fs = 1000 = 1s), come suggerito nel documento.
Ora le mie domande sono:
- Le formule f2 e f3 restituiscono lo stesso risultato per il segnale di chirp puro. Penso che sia buono, poiché calcolano lo stesso. I tre metodi di approssimazione non restituiscono lo stesso, nemmeno qualcosa che gli è vicino! Perché è così? (Spero non sia solo un bug di programmazione ...)
- Sebbene ritornino allo stesso modo, specialmente alla fine della trama, iniziano a "muovere" molto . Qual è la spiegazione per questo? Ho pensato per la prima volta a qualcosa come l'aliasing, ma la mia frequenza di campionamento è piuttosto elevata, rispetto alla frequenza dei segnali, quindi penso che possa essere esclusa.
Almeno f2 e f3 sembrano funzionare in modo appropriato su un segnale di chirp puro, ma tutti i metodi, compresi f2 e f3 sembrano fallire in modo orribile, quando si tratta di più di una frequenza nel segnale. In realtà avere più di una frequenza in un segnale è piuttosto sempre il caso. Quindi come si può ottenere la (più o meno) frequenza istantanea corretta?
- In realtà non so nemmeno cosa aspettarmi, quando nel segnale è presente più di una frequenza. Il calcolo restituisce un numero per un dato momento, quindi cosa dovrebbe fare quando, come qui, sono presenti più frequenze? Restituire la media di tutte le frequenze o qualcosa del genere?
E la mia domanda probabilmente più importante è: come viene gestita in un software reale ed elaborato? Diciamo che voglio conoscere la frequenza istantanea del segnale modulato a 1,75 s, e ho scelto il metodo f2, quindi posso essere "fortunato" e ottenere un numero vicino a 6 [Hz] che è molto probabilmente la risposta corretta, oppure I scelgo i miei risultati pochi campioni accanto ad esso e all'improvviso ottengo un po 'cablato, troppo alto, risultato, perché purtroppo ho scelto un valore nel picco. Come può essere gestito? Postprocessandolo con un filtro medio o addirittura migliore? Penso che anche questo potrebbe diventare davvero difficile, specialmente nelle regioni in cui molti picchi sono uno accanto all'altro.
E un'ultima domanda, non così importante, perché la maggior parte dei documenti che trovo sulle frequenze istantanee provengono dall'area geografica, specialmente nel calcolo di eventi sismografici come i terremoti. Il documento di Barne lo prende anche come esempio. La frequenza istantanea non è interessante in molte aree?
Fin qui, sono molto grato per ogni risposta, specialmente quando qualcuno mi dà suggerimenti su come implementarlo in un vero progetto software ;)
Cordiali saluti, Patrick