Main Content

La traducción de esta página aún no se ha actualizado a la versión más reciente. Haga clic aquí para ver la última versión en inglés.

Analizar picos

Este ejemplo muestra cómo realizar análisis básicos de picos. Le ayudará a responder a preguntas como las siguientes: ¿Cómo puedo encontrar picos en mi señal? ¿Cómo puedo medir la distancia entre picos? ¿Cómo puedo medir la amplitud de los picos de una señal afectada por una tendencia? ¿Cómo puedo encontrar picos en una señal con ruido? ¿Cómo puedo encontrar mínimos locales?

Buscar máximos o picos

El número relativo de manchas solares en Zúrich mide tanto el número como el tamaño de las manchas solares. Utilice la función findpeaks para buscar las ubicaciones y el valor de los picos.

load sunspot.dat
year = sunspot(:,1); 
relNums = sunspot(:,2);
findpeaks(relNums,year)
xlabel('Year')
ylabel('Sunspot Number')
title('Find All Peaks')

Figure contains an axes object. The axes object with title Find All Peaks, xlabel Year, ylabel Sunspot Number contains 2 objects of type line. One or more of the lines displays its values using only markers

La gráfica anterior muestra los números de manchas solares tabulados en un periodo de 300 años y etiqueta los picos detectados. La siguiente sección muestra cómo medir la distancia entre estos picos.

Medir la distancia entre picos

Parece que los picos, en la señal, aparecen a intervalos regulares. Sin embargo, algunos picos están muy próximos entre sí. Puede utilizar la propiedad MinPeakProminence para filtrar estos picos. Considere los picos que disminuyen a ambos lados en, al menos, 40 números relativos de manchas solares antes de encontrar un valor superior.

findpeaks(relNums,year,'MinPeakProminence',40)
xlabel('Year')
ylabel('Sunspot Number')
title('Find Prominent Peaks')

Figure contains an axes object. The axes object with title Find Prominent Peaks, xlabel Year, ylabel Sunspot Number contains 2 objects of type line. One or more of the lines displays its values using only markers

El siguiente histograma muestra la distribución de los intervalos de picos en años:

figure
[pks, locs] = findpeaks(relNums,year,'MinPeakProminence',40);
peakInterval = diff(locs);
histogram(peakInterval)
grid on
xlabel('Year Intervals')
ylabel('Frequency of Occurrence')
title('Histogram of Peak Intervals (years)')

Figure contains an axes object. The axes object with title Histogram of Peak Intervals (years), xlabel Year Intervals, ylabel Frequency of Occurrence contains an object of type histogram.

AverageDistance_Peaks = mean(diff(locs))
AverageDistance_Peaks = 10.9600

La distribución muestra que la mayoría de intervalos de picos se encuentra entre 10 y 12 años, lo que indica que la señal presenta una naturaleza cíclica. Además, el intervalo promedio de 10,96 años entre los picos coincide con la actividad cíclica conocida de manchas solares que es de 11 años.

Buscar picos en señales cortadas o saturadas

Puede considerar los picos planos como picos o excluirlos. En este último caso, se especifica una excursión mínima, que se define como la diferencia de amplitud entre un pico y sus vecinos más cercanos, utilizando la propiedad threshold.

load clippedpeaks.mat

figure

% Show all peaks in the first plot
ax(1) = subplot(2,1,1);
findpeaks(saturatedData)
xlabel('Samples')
ylabel('Amplitude')
title('Detecting Saturated Peaks')

% Specify a minimum excursion in the second plot
ax(2) = subplot(2,1,2);
findpeaks(saturatedData,'threshold',5)
xlabel('Samples')
ylabel('Amplitude')
title('Filtering Out Saturated Peaks')

% link and zoom in to show the changes
linkaxes(ax(1:2),'xy')
axis(ax,[50 70 0 250])

Figure contains 2 axes objects. Axes object 1 with title Detecting Saturated Peaks, xlabel Samples, ylabel Amplitude contains 2 objects of type line. One or more of the lines displays its values using only markers Axes object 2 with title Filtering Out Saturated Peaks, xlabel Samples, ylabel Amplitude contains 2 objects of type line. One or more of the lines displays its values using only markers

La primera subgráfica muestra que, en el caso de un pico plano, el borde ascendente se detecta como el pico. La segunda subgráfica muestra que especificar un umbral puede ayudar a rechazar picos planos.

Medir las amplitudes de los picos

Este ejemplo muestra el análisis de los picos en una señal de ECG (electrocardiograma). Un ECG es una medida de la actividad eléctrica del corazón en el tiempo. La señal se mide utilizando electrodos, que van pegados a la piel, y es sensible a alteraciones como interferencias de la fuente de alimentación y ruidos generados por objetos en movimiento.

load noisyecg.mat
t = 1:length(noisyECG_withTrend);

figure
plot(t,noisyECG_withTrend)
title('Signal with a Trend')
xlabel('Samples');
ylabel('Voltage(mV)')
legend('Noisy ECG Signal')
grid on

Figure contains an axes object. The axes object with title Signal with a Trend, xlabel Samples, ylabel Voltage(mV) contains an object of type line. This object represents Noisy ECG Signal.

Eliminación de tendencia de datos

La señal anterior presenta un cambio de partida, por lo que no representa la amplitud real. Para eliminar la tendencia, ajuste a la señal un polinomio de orden bajo y utilice el polinomio para eliminar la tendencia.

[p,s,mu] = polyfit((1:numel(noisyECG_withTrend))',noisyECG_withTrend,6);
f_y = polyval(p,(1:numel(noisyECG_withTrend))',[],mu);

ECG_data = noisyECG_withTrend - f_y;        % Detrend data

figure
plot(t,ECG_data)
grid on
ax = axis;
axis([ax(1:2) -1.2 1.2])
title('Detrended ECG Signal')
xlabel('Samples')
ylabel('Voltage(mV)')
legend('Detrended ECG Signal')

Figure contains an axes object. The axes object with title Detrended ECG Signal, xlabel Samples, ylabel Voltage(mV) contains an object of type line. This object represents Detrended ECG Signal.

Una vez eliminada la tendencia, busque el complejo QRS, que es el pico más prominente que se repite en la señal del ECG. El complejo QRS se corresponde con la despolarización de los ventrículos derecho e izquierdo del corazón humano. Puede utilizarse para determinar el ritmo cardíaco o predecir anomalías en la actividad cardíaca. La siguiente figura muestra la forma del complejo QRS en una señal de ECG.

Utilizar umbrales para buscar picos de interés

El complejo QRS está formado por tres componentes principales: onda Q, onda R, onda S. Las ondas R pueden detectarse utilizando umbrales de picos por encima de 0,5 mV. Tenga en cuenta que las ondas R se encuentran separadas por más de 200 muestras. Utilice esta información para eliminar picos no deseados especificando una "MinPeakDistance".

[~,locs_Rwave] = findpeaks(ECG_data,'MinPeakHeight',0.5,...
                                    'MinPeakDistance',200);

Para detectar las ondas S, busque los mínimos locales en la señal y aplique los umbrales apropiados.

Búsqueda de mínimos locales en una señal

Es posible detectar mínimos locales buscando picos en una versión invertida de la señal original.

ECG_inverted = -ECG_data;
[~,locs_Swave] = findpeaks(ECG_inverted,'MinPeakHeight',0.5,...
                                        'MinPeakDistance',200);

La siguiente gráfica muestra las ondas R y las ondas S detectadas en la señal.

figure
hold on 
plot(t,ECG_data)
plot(locs_Rwave,ECG_data(locs_Rwave),'rv','MarkerFaceColor','r')
plot(locs_Swave,ECG_data(locs_Swave),'rs','MarkerFaceColor','b')
axis([0 1850 -1.1 1.1])
grid on
legend('ECG Signal','R waves','S waves')
xlabel('Samples')
ylabel('Voltage(mV)')
title('R wave and S wave in Noisy ECG Signal')

Figure contains an axes object. The axes object with title R wave and S wave in Noisy ECG Signal, xlabel Samples, ylabel Voltage(mV) contains 3 objects of type line. One or more of the lines displays its values using only markers These objects represent ECG Signal, R waves, S waves.

A continuación, intentaremos determinar las ubicaciones de las ondas Q. Al utilizar umbrales en los picos para localizar las ondas Q, detectamos picos no deseados, ya que las ondas Q están ocultas por el ruido. Primero filtramos la señal y después buscamos los picos. Se utiliza el filtrado de Savitzky-Golay para eliminar el ruido en la señal.

smoothECG = sgolayfilt(ECG_data,7,21);

figure
plot(t,ECG_data,'b',t,smoothECG,'r')
grid on
axis tight
xlabel('Samples')
ylabel('Voltage(mV)')
legend('Noisy ECG Signal','Filtered Signal')
title('Filtering Noisy ECG Signal')

Figure contains an axes object. The axes object with title Filtering Noisy ECG Signal, xlabel Samples, ylabel Voltage(mV) contains 2 objects of type line. These objects represent Noisy ECG Signal, Filtered Signal.

Realizamos la detección de picos en la señal suavizada y utilizamos indexación lógica para buscar las ubicaciones de las ondas Q.

[~,min_locs] = findpeaks(-smoothECG,'MinPeakDistance',40);

% Peaks between -0.2mV and -0.5mV
locs_Qwave = min_locs(smoothECG(min_locs)>-0.5 & smoothECG(min_locs)<-0.2);

figure
hold on
plot(t,smoothECG); 
plot(locs_Qwave,smoothECG(locs_Qwave),'rs','MarkerFaceColor','g')
plot(locs_Rwave,smoothECG(locs_Rwave),'rv','MarkerFaceColor','r')
plot(locs_Swave,smoothECG(locs_Swave),'rs','MarkerFaceColor','b')
grid on
title('Thresholding Peaks in Signal')
xlabel('Samples')
ylabel('Voltage(mV)')
ax = axis;
axis([0 1850 -1.1 1.1])
legend('Smooth ECG signal','Q wave','R wave','S wave')

Figure contains an axes object. The axes object with title Thresholding Peaks in Signal, xlabel Samples, ylabel Voltage(mV) contains 4 objects of type line. One or more of the lines displays its values using only markers These objects represent Smooth ECG signal, Q wave, R wave, S wave.

La figura anterior muestra cómo el complejo QRS se ha detectado correctamente en la señal del ECG con ruido.

Error entre señal con ruido y suavizada

Observe la diferencia media entre el complejo QRS en la señal filtrada en bruto y con la tendencia eliminada.

% Values of the Extrema
[val_Qwave, val_Rwave, val_Swave] = deal(smoothECG(locs_Qwave), smoothECG(locs_Rwave), smoothECG(locs_Swave));

meanError_Qwave = mean((noisyECG_withTrend(locs_Qwave) - val_Qwave))
meanError_Qwave = 0.2771
meanError_Rwave = mean((noisyECG_withTrend(locs_Rwave) - val_Rwave))
meanError_Rwave = 0.3476
meanError_Swave = mean((noisyECG_withTrend(locs_Swave) - val_Swave))
meanError_Swave = 0.1844

Esta demuestra que es fundamental eliminar la tendencia de una señal con ruido para realizar un análisis eficiente de los picos.

Propiedades de los picos

Algunas de las propiedades importantes de los picos son el tiempo de subida, el tiempo de caída, el nivel de subida y el nivel de caída. Estas propiedades se calculan para cada complejo QRS en la señal del ECG. Los valores medios de estas propiedades se muestran en la siguiente figura.

avg_riseTime = mean(locs_Rwave-locs_Qwave); % Average Rise time
avg_fallTime = mean(locs_Swave-locs_Rwave); % Average Fall time
avg_riseLevel = mean(val_Rwave-val_Qwave);  % Average Rise Level
avg_fallLevel = mean(val_Rwave-val_Swave);  % Average Fall Level

helperPeakAnalysisPlot(t,smoothECG,...
                    locs_Qwave,locs_Rwave,locs_Swave,...
                    val_Qwave,val_Rwave,val_Swave,...
                    avg_riseTime,avg_fallTime,...
                    avg_riseLevel,avg_fallLevel)

Figure contains an axes object. The axes object with title QRS-complex in an ECG signal, xlabel Samples, ylabel Voltage(mV) contains 11 objects of type line, text. One or more of the lines displays its values using only markers These objects represent QRS-Complex, Peak, Minima.

Consulte también