Find similarities between two signals

35 views (last 30 days)
Gus
Gus on 2 Apr 2024
Commented: Star Strider on 2 Apr 2024
I'm trying to find similarities between my template signal and a lot of other signals. I have tried to use cross-correlation (xcorr) and also peak detection on the signals to find similarities between the template and the signals. The problem is that the algorithm for finding signals that are similar does not work as a want.
Below are my template signal (Figure 1)
and here is one signal that the cross-correltion fought were similar (Figure 2)
Although the two signals have similarities, figure 2 does not contain the high peaks as in figure 1. I want to find signals that contain those clear peaks. I have tried to solve this by using findpeaks with two conditions "MinPeaksHeights'' and "MinPeakDistance'’ to find those bigger peaks and exclude smaller peaks. Somehow it still manages to sometimes find peaks and similarities between signals that does not look similar and I don't really know why.
Is there a better way to find the same peak characteristics as the template?
Below are the part where I try to perform the algorithm to identify similar signals to the template:
template = (template - mean(template)) / std(template);
signal_normalized = zscore(signal, [], 1); % Normalize along time axis
% Define correlation threshold for component selection
correlation_threshold = 0.4;
matching_components_indices = [];
for k = 1:size(signal, 2)
% Calculate cross-correlation with the template
correlation_with_template = max(xcorr(template, signal_normalized(:, k), 'coeff'));
% Check if correlation is above the threshold
if correlation_with_template > correlation_threshold
matching_components_indices = [matching_components_indices, k];
end
end
% Sets amplitude threshold for peak detection
amplitude_threshold = 25;
min_peak_distance = 100; % Min distance between peaks
% Find peaks in the matching components
selected_components_indices = [];
for k = 1:length(matching_components_indices)
[pks_pos, locs_pos] = findpeaks(signal(:, matching_components_indices(k)), ...
'MinPeakHeight', amplitude_threshold, ...
'MinPeakDistance', min_peak_distance);
[pks_neg, locs_neg] = findpeaks(-signal(:, matching_components_indices(k)), ...
'MinPeakHeight', amplitude_threshold, ...
'MinPeakDistance', min_peak_distance);
% Combine positive and negative peak locations
pks = [pks_pos; pks_neg];
locs = [locs_neg; locs_pos];
% Check if any peak exceeds the threshold
if length(pks) > 2
selected_components_indices = [selected_components_indices, matching_components_indices(1)];
found_signal(:,m) = signal(:, selected_components_indices(1));
m = m + 1;
end
Maybe I can improve the peak detection part?
Thanks for any help. If I was unclear, let me know
  5 Comments
Gus
Gus on 2 Apr 2024
@Star Strider Thanks for the reply. The problem with "MinPeakPromience" is that some peaks it finds have similar peaks (amplitude) but not always similar shape of the peak structure, if you know what I mean. The peaks I am looking for always have similar "uphill" as "downhill" (from the peaks perspective), they have similar slopes that is. I thought maybe it's possible to calculate the derivative of the curve of both the "uphill" and "downhill", and then only look for those kinds of derivative near peaks when looking at other signals to find similarities in peaks?
Star Strider
Star Strider on 2 Apr 2024
My pleasure!
It might be necessary to filter the data first, probably with a lowpass filter to eliminate the high-frequency noise. (A bandpass filter would probably eliminate the baseline drift as well, so consider that option if that is the result you want.)
You can determine the optimal frequencies for the filter you choose (if that is what you want to do) by taking the fft of both signals (since you will want to use the same filter for both), and then desiging the filter appropriatel using that information. This also assumes both signals have the same sampling frequency, as they must for this sort of approach.

Sign in to comment.

Answers (2)

Constantino Carlos Reyes-Aldasoro
Perhaps this file exchange analysing an ECG signal can give you some ideas:
https://uk.mathworks.com/matlabcentral/fileexchange/68246-visualization-and-analysis-of-an-electrocardiogram-signal?focused=7fbc0610-5e23-435e-a271-ddd80d1065d0&tab=example

Image Analyst
Image Analyst on 2 Apr 2024
The question is really what kind of metric(s) would be useful for you?
How about RMS difference? rms
How about mean absolute deviation or median absolute deviation: mad
How about just locating peaks and finding the distance between peaks of the test signal to the reference signal? findpeaks
How about the correlation coefficient? corrcoef
Are the signals aligned already because some of those metrics need the signals to be aligned if you want to compare the shape of the signal. Or they might be a good metric of how misaligned they are.

Products


Release

R2023b

Community Treasure Hunt

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

Start Hunting!