Soy nuevo en el principio de calcular la frecuencia instantánea y se me ocurrieron muchas preguntas al respecto. Los encontrará en una lista de puntos al final de este texto. El texto puede ser un poco largo, discúlpeme por eso, pero realmente intenté trabajar en ese problema por mi cuenta.
Así que estoy interesado en la frecuencia instantánea de una señal de valor real . El cálculo se realiza con la ayuda de una señal analítica , donde es la transformación de Hilbert de .
Para calcular las frecuencias instantáneas de la señal analítica seguí el artículo:
El cálculo de la frecuencia instantánea y el ancho de banda instantáneo por Arthur E. Barns a partir de 1992. En este artículo presenta múltiples métodos para calcular la frecuencia instantánea. Escribo todas las fórmulas que propuso (y usé) en un momento.
Para "aprender", jugué con unas señales muy simples y dos un poco más complejas, en MATLAB, y quería obtener sus frecuencias instantáneas.
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
Las gráficas en el dominio del tiempo de esas tres señales tienen el siguiente aspecto:
Las gráficas de todas las frecuencias instantáneas que obtuve después de aplicar todos los métodos del documento son las siguientes:
Frecuencias instantáneas de la señal de chirp puro: frecuencias instantáneas de la señal de chirp con sinusoide agregado: frecuencias instantáneas de la señal de chirp modulada: tenga en cuenta que en las tres imágenes, el eje y de los gráficos 3 y 4 se amplía, por lo que las amplitudes de esos las señales son muy pequeñas!
La primera posibilidad de pasar de la señal analítica a la frecuencia instantánea es:
donde es la fase instantánea. Creo que este es el método más común utilizado hoy en día, al menos en la página web de MATLAB se calcula de esa manera. El código tiene el siguiente aspecto:
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
En el artículo, Graneros ahora sugiere (o más bien dichas compilaciones) otras cuatro formas de calcular frecuencias instantáneas a partir de la señal analítica. También menciona la fórmula superior, pero es la opinión de que no es práctica debido a las ambigüedades en la fase. Supongo que no conocía el unwrap()
método, o para ser más precisos, las matemáticas detrás de él. (Yo mismo aprendí sobre ese método hoy, al mirar otros códigos fuente en frecuencias instantáneas)
En su artículo, la fórmula tiene la etiqueta Número (2), por lo tanto, le di a f (t) el índice 2. Todos los demás índices corresponden de la misma manera a sus números en el documento.
Debido a las ambigüedades en la fase, sugiere más bien:
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
Luego Barner da tres fórmulas más que denomina "aproximaciones de frecuencia instantánea":
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
En las 3 aproximaciones, las fórmulas T se establecieron en Fs (T = Fs = 1000 = 1s), como se sugiere en el documento.
Ahora mis preguntas son:
- Las fórmulas f2 y f3 devuelven el mismo resultado para la señal de chirp puro. Creo que es bueno, ya que calculan lo mismo. ¡Los tres métodos de aproximación no devuelven lo mismo, ni siquiera algo que esté cerca! ¿Por qué es ese el caso? (Espero que no sea solo un error de programación ...)
- Aunque devuelven lo mismo, especialmente al final de la trama, comienzan a 'moverse' mucho . ¿Cuál es la explicación para eso? Primero pensé en algo como el alias, pero mi frecuencia de muestreo es bastante alta, en comparación con la frecuencia de las señales, por lo que creo que puede excluirse.
Al menos f2 y f3 parecen funcionar adecuadamente en una señal de chirp puro, pero todos los métodos, incluidos f2 y f3, parecen fallar horriblemente, cuando se trata de más de una frecuencia en la señal. En realidad, tener más de una frecuencia en una señal es siempre el caso. Entonces, ¿cómo se puede obtener la frecuencia instantánea correcta (más o menos)?
- De hecho, ni siquiera sé qué esperar cuando hay más de una frecuencia presente en la señal. El cálculo devuelve un número para un punto dado en el tiempo, entonces, ¿qué debería hacer cuando, como aquí, hay más frecuencias presentes? ¿Devuelve el promedio de todas las frecuencias o algo así?
Y mi pregunta probablemente más importante es, ¿cómo se maneja eso en un software real y elaborado? Digamos que quiero saber la frecuencia instantánea de la señal modulada a 1.75 s, y elegí el método f2, de lo que puedo ser 'afortunado' y obtener un número cercano a 6 [Hz] que probablemente sea la respuesta correcta, o yo escojo mis resultados con algunas muestras al lado y de repente obtengo un resultado cableado, demasiado alto, porque desafortunadamente elegí un valor en el pico. ¿Cómo se puede manejar esto? ¿Postprocesándolo con un filtro medio o incluso mejor? Creo que incluso eso podría ser realmente difícil, especialmente en regiones donde hay muchos picos uno al lado del otro.
Y una última pregunta, no tan importante, ¿por qué es que la mayoría de los trabajos que encuentro sobre frecuencias instantáneas son del área de la geografía, especialmente en el cálculo de eventos sismológicos como los terremotos. El artículo de Barne también toma eso como un ejemplo. ¿No es interesante la frecuencia instantánea en muchas áreas?
Hasta ahora, estoy muy agradecido por cada respuesta, especialmente cuando alguien me da consejos sobre cómo implementarlo en un proyecto de software real ;)
Saludos cordiales, Patrick