Znam zasadę obliczania częstotliwości chwilowej i wpadłem na wiele pytań na jej temat. Znajdziesz je wszystkie na liście punktorów na końcu tego tekstu. Tekst może być trochę długi, przepraszam za to, ale naprawdę próbowałem samodzielnie rozwiązać ten problem.
Więc interesuje mnie częstotliwość chwilowa sygnału o wartościach rzeczywistych . Obliczenia wykonuje się za pomocą sygnału analitycznego, gdzie jest transformacją Hilberta .
Aby obliczyć chwilowe częstotliwości z sygnału analitycznego Śledziłem artykuł:
Obliczanie częstotliwości chwilowej i chwilowej przepustowości przez Arthura E. Barnsa z 1992 r. W tym artykule wprowadza wiele metod obliczania częstotliwości chwilowej. Zapisuję wszystkie formuły, które zaproponował (i użyłem) za chwilę.
W celu „uczenia się” bawiłem się w MATLAB bardzo prostymi i dwoma nieco bardziej złożonymi sygnałami i chciałem uzyskać ich chwilowe częstotliwości.
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
Wykresy w dziedzinie czasu tych trzech sygnałów wyglądają następująco:
Wykresy wszystkich chwilowych częstotliwości, które otrzymałem po zastosowaniu wszystkich metod z papieru, są następujące:
Chwilowe częstotliwości czystego sygnału ćwierkającego: Chwilowe częstotliwości sygnału ćwierkającego z dodanym sinusoidą: Chwilowe częstotliwości modulowanego sygnału ćwierkającego: Należy pamiętać, że na wszystkich trzech obrazach oś y wykresu 3 i 4 jest powiększona, więc amplitudy tych sygnały są bardzo małe!
Pierwszą możliwością przejścia z sygnału analitycznego na częstotliwość chwilową jest:
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
W artykule Barns sugeruje teraz (a raczej wspomnianą kompilację) cztery inne sposoby obliczania chwilowych częstotliwości z sygnału analitycznego. Wspomina także górną formułę, ale jest zdania, że jest ona niepraktyczna ze względu na niejasności w fazie. Wydaje mi się, że nie znał unwrap()
metody ani, mówiąc ściślej, matematyki za nią. (Ja sam dowiedziałem się o tej metodzie dopiero dziś, kiedy patrzę na inne kody źródłowe na chwilowych częstotliwościach)
W jego pracy formuła ma etykietę Numer (2), dlatego nadałem f (t) indeks 2. Wszystkie pozostałe indeksy odpowiadają w ten sam sposób ich liczbom w pracy.
Z powodu niejasności fazowych sugeruje raczej:
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
Następnie Barner podaje jeszcze trzy formuły, które nazywa „chwilowymi przybliżeniami częstotliwości”:
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
We wszystkich 3 przybliżeniach wzory T zostały ustawione na Fs (T = Fs = 1000 = 1s), jak sugerowano w pracy.
Teraz moje pytania to:
- Formuły f2 i f3 zwracają ten sam wynik dla czystego sygnału ćwierkającego. Myślę, że to dobrze, ponieważ obliczają to samo. Trzy metody aproksymacji nie zwracają tego samego, nawet czegoś, co jest blisko! Dlaczego tak jest? (Mam nadzieję, że to nie tylko błąd programowy ...)
- Chociaż wrócą same, zwłaszcza na końcu działki zaczną „Wiggle” dużo . Jakie jest tego wytłumaczenie? Najpierw pomyślałem o aliasingu, ale moja częstotliwość próbkowania jest dość wysoka w porównaniu z częstotliwością sygnałów, więc myślę, że można to wykluczyć.
Wydaje się, że przynajmniej f2 i f3 działają poprawnie na czysty sygnał ćwierkający, ale wszystkie metody, w tym f2 i f3, wydają się okropnie zawodzić, jeśli chodzi o więcej niż jedną częstotliwość w sygnale. W rzeczywistości zawsze występuje więcej niż jedna częstotliwość w sygnale. Jak więc uzyskać (mniej więcej) prawidłową częstotliwość chwilową?
- Właściwie nawet nie wiem, czego się spodziewać, gdy w sygnale jest więcej niż jedna częstotliwość. Obliczenia zwracają jedną liczbę dla danego punktu w czasie, więc co należy zrobić, gdy, tak jak tutaj, jest więcej częstotliwości? Zwraca średnią wszystkich częstotliwości czy coś takiego?
I moim prawdopodobnie najważniejszym pytaniem jest, jak sobie z tym poradzić w prawdziwym i rozbudowanym oprogramowaniu? Powiedzmy, że chcę znać chwilową częstotliwość modulowanego sygnału na 1,75 s, i wybrałem metodę f2, niż mogę być „szczęśliwy” i uzyskać liczbę bliską 6 [Hz], co jest najprawdopodobniej poprawną odpowiedzią, lub ja wybierz moje wyniki obok kilku próbek i nagle dostaję trochę przewodowego wyniku, zbyt wysokiego, ponieważ niestety wybrałem wartość w piku. Jak sobie z tym poradzić? Czy przetwarzając go ze średnim, a nawet lepszym filtrem mediany? Myślę, że nawet to może stać się naprawdę trudne, szczególnie w regionach, w których wiele skoków znajduje się obok siebie.
I ostatnie, nie tak ważne pytanie, dlaczego większość dokumentów, które znajduję na temat częstotliwości chwilowych, pochodzi z obszaru geografii, szczególnie w obliczaniu zdarzeń sejsmograficznych, takich jak trzęsienia ziemi. Papier Barne'a również bierze to za przykład. Czy częstotliwość chwilowa nie jest interesująca w wielu obszarach?
Na razie tyle, jestem bardzo wdzięczny za każdą odpowiedź, szczególnie gdy ktoś daje mi wskazówki, jak zaimplementować ją w prawdziwym projekcie oprogramowania ;)
Z pozdrowieniami, Patrick