How to divide a signal into groups of peaks

6 visualizaciones (últimos 30 días)
cob
cob el 13 de Jul. de 2015
Comentada: Surabhi KS el 30 de Sept. de 2021
Hi, i have an audio sample , which im trying to divide into groups of signals , for energy and time analysis . here is the signal :
what i'm trying to do is, to get the start and the end indexes of this 4 chunks. right now i dont have a clue how to get this done . Thank you
  4 comentarios
Luis Gomes Perini
Luis Gomes Perini el 13 de Jul. de 2015
Hi,
your question is how to develop an algorithm that captures such peaks, or how to determine the start/end of peaks ?
Cheers, Luis Gomes Perini
cob
cob el 13 de Jul. de 2015
the main purpose is to count how many chunks/peaks, with similar energy and duration between them , in a specific length , for now i want to determine the start index and the end index of such peak/chunk , which will help me in the future analysis . Of course its not a place to ask for algorithm development , its on my own.
Thank you in advance.

Iniciar sesión para comentar.

Respuesta aceptada

Star Strider
Star Strider el 13 de Jul. de 2015
This is likely the most difficult signal you’ve presented. Probably the best way to produce a derived signal that would allow you to isolate the parts of your signal of interest is to use a bandpass filter and then a Savitzky-Golay filter.
The code:
cs = load('cob signal.mat');
S1 = cs.coarse_d(:,1);
S2 = cs.coarse_d(:,2);
Fs = cs.fs_d;
Fn = Fs/2;
Ts = 1/Fs;
T = [0:length(S1)-1]*Ts;
Wp = [950 1000]/Fn;
Ws = [0.5 1/0.5].*Wp;
Rp = 1;
Rs = 30;
[n,Wn] = buttord(Wp, Ws, Rp, Rs);
[b, a] = butter(n, Wn);
[sos, g] = tf2sos(b, a);
S1F = filtfilt(sos, g, S1);
SGS1 = sgolayfilt(abs(S1F), 1, 901);
figure(1)
plot(T, S1)
hold on
% plot(T, S1F)
plot(T, SGS1, 'LineWidth',1.3)
hold off
grid
% axis([0.5 1.5 ylim])
The first ‘burst’ of the original signal (with the Savitzky-Golay filter of the bandpass filtered signal superimposed) is:
You could simply threshold the sgolayfilt output, or use findpeaks to determine the locations of each ‘burst’. I didn’t comment-document the code, because it’s similar to my previous filter designs (documented), the only novelty being the addition of sgolayfilt.
  2 comentarios
cob
cob el 13 de Jul. de 2015
WOW , thank you very much , i've asked only one little thing , and you just solved the whole problem , again thank you . Can you please explain why do you use the commands ts2sos , and filtfilt and how you determined Wp valuse ?
again thank you very much
Star Strider
Star Strider el 13 de Jul. de 2015
My pleasure!
One item I left out was the fft code, which is how I arrived at the filter design Wp values. I include it here:
FS1 = fft(S1)/length(S1);
Fv = linspace(0, 1, fix(length(FS1)/2)+1)*Fn;
Ix = 1:length(Fv);
figure(2)
plot(Fv, abs(FS1(Ix)))
grid
axis([0 5E3 ylim])
I chose the frequency band that seemed to have the most energy, in order to make it easier for sgolayfilt. It took a bit of experimentation with the bandpass and Savitzky-Golay filters to get a result I liked well enough to post.
Transfer-function designs can be unstable and produce anomalous results, so I use the second-order section representation of a filter (therefore tf2sos) to provide stability. I usually use freqz to assess filter stability of the transfer-function and second-order-section implementations, just to be sure they work. (MATLAB suggests this in its documentation, and one of the filter design tools does it automatically.)
The filtfilt function (as opposed to filter) is phase-neutral (the sort of behaviour that favours the Bessel design in hardware implementations). The filtfilt function renders all discrete filters phase-neutral.
My detailed explanation of filter design is here.
As always, my pleasure. Biomedical signal processing is of particular interest to me, so I learn something from every new problem.

Iniciar sesión para comentar.

Más respuestas (1)

Image Analyst
Image Analyst el 13 de Jul. de 2015
Editada: Image Analyst el 26 de Dic. de 2020
Well, being an image analyst, I came up with a different approach. You can get a logical array defining what's a signal and what's the quiet parts with just two lines of code, one to threshold and one to do a morphological filter. Here's a full blown demo:
% Setup - read in the signal and plot it.
s=load('signal.mat')
signal = s.coarse_d;
subplot(3,1,1);
plot(signal, '-', 'Color', [0,.5,0]);
grid on;
% MAIN CODE IS THE FOLLOWING TWO LINES OF CODE.
% Threshold the signal
lowSignal = abs(signal) < 0.1;
% Remove stretches less than 10,000 elements long.
% And invert it to get the high signal areas instead of the quiet areas.
lowSignal = ~bwareaopen(lowSignal, 10000);
% Now we're done. Plot the results.
subplot(3,1,2);
plot(lowSignal, 'b-', 'LineWidth', 2);
grid on;
% Plot both on the same graph now.
subplot(3,1,3);
plot(signal, '-', 'Color', [0,.5,0]);
hold on;
plot(lowSignal, 'b-', 'LineWidth', 2);
grid on;
  8 comentarios
Image Analyst
Image Analyst el 13 de Feb. de 2019
You'd have to extract each segment using indexing then put them into a cell array because each segment won't have the same number of elements and thus cannot be put into a double array (unless the ends were padded with zeros or nans or something.
Surabhi KS
Surabhi KS el 30 de Sept. de 2021
You can make a class object.

Iniciar sesión para comentar.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by