How can I smooth a signal while preserving peaks in MATLAB (R2013a)?
39 views (last 30 days)
Show older comments
MathWorks Support Team
on 25 Oct 2013
Answered: Image Analyst
on 17 Nov 2020
I have a noisy signal with sharp peaks. I would like to smoothe the data while preserving the peaks. How can I do that?
Accepted Answer
MathWorks Support Team
on 25 Oct 2013
In order to smoothe noisy data while preserving the peaks, you can use the function MSSGOLAY, which smoothes a signal with peaks using least-squares polynomial or MSLOWESS, which smoothes a signal with peaks using nonparametric method.
More information on either of these algorithms can be found in the Documentation:
>> doc mssgolay
>> doc mslowess
1 Comment
Image Analyst
on 15 Feb 2014
The original algorithm by Savitzky and Golay assumes the input vector, X, has uniformly spaced separation units, while mssgolay() also allows one that is not uniformly spaced. mssgolay() is in the Bioinformatics Toolbox . sgolay() is in the Signal Processing Toolbox.
More Answers (1)
Image Analyst
on 17 Nov 2020
Alternatively you could
- Find the peaks (their indexes and values) with [peakValues, indexes] = findpeaks(signal).
- Generate an additional smoothed signal somehow, for example with movmean() or sgolayfilt(). smoothedSignal = movmean(signal, 21)
- Assign the values of the original signal to the corresponding locations in the smoothed signal to replace the smoothed values with the original peak values.
% Create sample signal with peaks
numPoints = 200;
t = linspace(0, 2*pi, numPoints);
signal = cos(t) + 1;
% Add a small amount of noise to it - small enough that we can smooth it away.
signal = signal + 0.5 * rand(1, length(t));
% Put random peaks on it.
indexes1 = randperm(length(t), 8); % 8 randomly located peaks.
signal(indexes1) = signal(indexes1) + 2;
% Plot it.
subplot(3, 1, 1);
plot(t, signal, 'b.-', 'LineWidth', 2, 'MarkerSize', 15);
grid on;
xlabel('time');
ylabel('signal')
% Find the peaks
[peakValues, indexes2] = findpeaks(signal, 'Threshold', 1);
% Plot peaks over original signal.
hold on;
plot(t(indexes2), peakValues, 'rv', 'LineWidth', 2, 'MarkerSize', 15);
title('Original Signal with Peaks Identified');
% Smooth the signal. (With a little more effort you could smooth only the non-peak values so the peaks don't influence the smoothed result.)
nonPeakindexes = setdiff(1:length(t), indexes2);
smoothedSignal = movmean(signal, 21);
% Plot it.
subplot(3, 1, 2);
plot(t, smoothedSignal, 'b.-', 'LineWidth', 2, 'MarkerSize', 15);
grid on;
xlabel('time');
ylabel('signal')
title('Smoothed Signal');
% Replace the original peak values at their original location and height.
finalSignal = smoothedSignal; % Initialize
finalSignal(indexes2) = signal(indexes2); % Replace smoothed value with original value.
% Plot it.
subplot(3, 1, 3);
plot(t, finalSignal, 'b.-', 'LineWidth', 2, 'MarkerSize', 15);
grid on;
xlabel('time');
ylabel('signal')
title('Smoothed Signal With Peaks Back In');
0 Comments
See Also
Categories
Find more on Signal Generation and Preprocessing in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!