Я новачок у принципі обчислення миттєвої частоти, і мені прийшло багато питань. Ви знайдете їх у списку кульових точок в кінці цього тексту. Текст може бути трохи довгим, вибачте мене за це, але я справді намагався працювати над цією проблемою самостійно.
Тож мене цікавить миттєва частота реального значення сигналу . Розрахунок проводиться за допомогою аналітичного сигналу , де - перетворення Гільберта .
Для обчислення миттєвих частот з аналітичного сигналу я дотримувався статті:
Розрахунок миттєвої частоти та миттєвої пропускної здатності за Артуром Е. Барнсом з 1992 р. У цій роботі він вводить декілька методів обчислення миттєвої частоти. Я записую всі формули, які він запропонував (і я використав) за мить.
Для «навчання» я грав у MATLAB дуже простим та двома трохи складнішими сигналами і хотів отримати їх миттєві частоти.
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
Діаграми у часовій області цих трьох сигналів виглядають наступним чином:
Діаграми всіх миттєвих частот, які я отримав після застосування всіх методів з паперу, такі:
Миттєві частоти чистого чирпінг-сигналу: миттєві частоти чирпінг-сигналу з доданим синусоїдом: миттєві частоти модульованого сигналу щебетання: зверніть увагу, що на всіх трьох зображеннях вісь y ділянок 3 та 4 збільшена, тому амплітуди цих сигнали дуже крихітні!
Перша можливість дістатись від аналітичного сигналу до миттєвої частоти:
де - миттєва фаза. Я думаю, що це найпоширеніший метод, який сьогодні використовується, принаймні на веб-сторінці MATLAB він розрахований саме так. Код виглядає наступним чином:
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
У статті Барнс тепер пропонує (а точніше сказане компілює) чотири інші способи обчислення миттєвих частот з аналітичного сигналу. Він також згадує верхню формулу, але вважає, що це недоцільно через неоднозначності у фазі. Я здогадуюсь, він не знав unwrap()
методу, а якщо бути точнішим математикою за ним. (Я сам дізнався про цей метод саме сьогодні, коли дивився на деякі інші вихідні коди миттєвих частот)
У своїй роботі формула має мітку Number (2), тому я дав f (t) індекс 2. Всі інші індекси відповідають однаково до їх номерів у роботі.
Через неоднозначності на етапі він радше пропонує:
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
У всіх 3-х наближеннях формули T було встановлено на Fs (T = Fs = 1000 = 1s), як було запропоновано у статті.
Тепер моє запитання:
- Формули f2 і f3 повертають однаковий результат для чистого щебетання сигналу. Я думаю, що це добре, оскільки вони обчислюють те саме. Три методи наближення не повертають одне і те ж, навіть не те, що близьке до нього! Чому це так? (Я сподіваюся, що це не просто помилка програмування ...)
- Хоча вони повертають те саме, особливо в кінці сюжету вони починають сильно хитатися . Яке пояснення цьому? Я спершу придумав щось на зразок псевдоніму, але моя частота вибірки досить висока, порівняно з частотою сигналів, тому я думаю, що це можна виключити.
Принаймні, f2 і f3, здається, підходять для чистого щебетання сигналу, але всі методи, включаючи f2 і f3, здаються жахливими, коли мова йде про більш ніж одну частоту в сигналі. Насправді наявність сигналу більше однієї частоти - це завжди завжди. Тож як можна отримати (більш-менш) правильну миттєву частоту?
- Я насправді навіть не знаю, чого очікувати, коли в сигналі присутня більше однієї частоти. Обчислення повертає одне число за певний момент часу, так що робити, коли, як і тут, більше частот? Повернути середнє значення всіх частот чи щось подібне?
І моє, мабуть, найважливіше запитання - як це обробляється в реальному і розробленому програмному забезпеченні? Скажімо, я хочу знати миттєву частоту модульованого сигналу на 1,75 с, і я вибрав метод f2, ніж мені може пощастить і отримати число, близьке до 6 [Гц], що, швидше за все, є правильною відповіддю, або я підбирайте мої результати кілька зразків поруч із нею і раптом я отримую деякий провід, шлях до високого результату, тому що я, на жаль, вибрав значення у шипі. Як це можна впоратися? Після обробки його середнім або навіть краще середнім фільтром? Я думаю, що навіть це може стати справді важким, особливо в регіонах, де багато шипів знаходяться поруч.
І одне останнє, не настільки важливе питання, чому так, що більшість робіт, які я знаходжу на миттєвих частотах, стосуються географічної області, особливо в обчисленні сейсмографічних подій, таких як землетруси. Папір Барна також бере це як приклад. Хіба миттєва частота не цікава в багатьох областях?
Ось це поки що, я дуже вдячний за кожну відповідь, особливо коли хтось дає мені поради, як її реалізувати в реальному програмному проекті ;)
З повагою, Патріку