How to Correct the baseline shift of the signal

20 ビュー (過去 30 日間)
amirhossein shahriari
amirhossein shahriari 2018 年 5 月 15 日
コメント済み: Image Analyst 2025 年 2 月 20 日
I am trying to correct the baseline of the signal (picture attached) by using a single exponential curve fit to adjust the baseline.
The data file is attached as well.

採用された回答

Star Strider
Star Strider 2018 年 5 月 16 日
編集済み: Star Strider 2018 年 5 月 16 日
I always use discrete filters to eliminate baseline drift, baseline offset, and high-frequency noise.
Try this:
[D,S] = xlsread('Book1GA.xls');
Tcl = regexp(S, '(\d\.\d+)', 'match'); % Time Values (Cell Array)
Tch = cell2mat([Tcl{:}]'); % Time Values (Character Array)
Tv = str2num(Tch); % Time Vector (Double)
L = numel(Tv);
Ts = mean(diff(Tv)); % Sampling Interval
Tsd = std(diff(Tv));
Fs = 1/Ts; % Sampling Frequency
Fn = Fs/2; % Nyquist Frequency
Dmd = D - mean(D);
FT_D = fft(Dmd)/L;
Fv = linspace(0, 1, fix(L/2)+1)*Fn; % Frequency Vector
Iv = 1:numel(Fv);
figure(1)
plot(Fv, abs(FT_D(Iv))*2)
grid
axis([0 25 ylim])
set(gca, 'XMinorTick','on')
xlabel('Frequency')
Wp = [2.1 15.0]/Fn; % Passband Frequency (Normalised)
Ws = [1.8 18.0]/Fn; % Stopband Frequency (Normalised)
Rp = 1; % Passband Ripple (dB)
Rs = 50; % Stopband Ripple (dB)
[n,Ws] = cheb2ord(Wp,Ws,Rp,Rs); % Filter Order
[z,p,k] = cheby2(n,Rs,Ws); % Filter Design, Sepcify Bandpass
[sos,g] = zp2sos(z,p,k); % Convert To Second-Order-Section For Stability
figure(2)
freqz(sos, 2^16, Fs) % Filter Bode Plot
D_Filtered = filtfilt(sos, g, D); % Filter Signal
figure(3)
plot(Tv, D_Filtered)
grid
xlabel('Time')
Experiment witht he passband and stopband frequencies to get the result you want. Note that in a bandpass filter, the passband frequency limnits must always be within the stopband frequency limits.
EDIT Adding the plot:
  10 件のコメント
amirhossein shahriari
amirhossein shahriari 2018 年 6 月 7 日
Thank you so much . I have tried to experiment other sets of my data with savitzky filter but still seems like this band pass filter you design are way better and I can get way better average of my action potentials. So do you know why some other filters like savitzky are not helpful enough for this type of data
Star Strider
Star Strider 2018 年 6 月 7 日
As always, my pleasure.
The Savitzky-Golay filter is primarily used for curve-smoothing (or at least that is my experience). It is quite good for that purpose. However for signal processing, I find it difficult to design functional filters with it, and prefer using frequency-selective filters such as those I use here. The Tips (link) section of the documentation describes the use of the Savitzky-Golay filter much better than I can.
Also, if you have R2018a or later, the bandpass (link) and related functions make filter design significantly easier. If you use the ‘d’ output from it with an IIR filter, remember to use the filtfilt function to do the actual filtering, not the filter function as suggested in the documentation (that I consider to be an error).

サインインしてコメントする。

その他の回答 (2 件)

Image Analyst
Image Analyst 2018 年 5 月 16 日
You might use fitnlm(), if you have the Statistics and Machine Learning Toolbox
[D, S] = xlsread('Book1GA.xls');
Tcl = regexp(S, '(\d\.\d+)', 'match'); % Time Values (Cell Array)
Tch = cell2mat([Tcl{:}]'); % Time Values (Character Array)
Tv = str2num(Tch); % Thanks to Star for figuring out how to get the time!
plot(Tv, D, 'b-')
grid on;
erodedSignal = imerode(D, ones(51, 1));
hold on;
plot(Tv, erodedSignal, 'r-', 'LineWidth', 2);
X = Tv;
Y = erodedSignal;
% Convert X and Y into a table, which is the form fitnlm() likes the input data to be in.
tbl = table(X, Y);
% Define the model as Y = a + exp(-b*x)
% Note how this "x" of modelfun is related to big X and big Y.
% x((:, 1) is actually X and x(:, 2) is actually Y - the first and second columns of the table.
modelfun = @(b,x) b(1) + b(2) * exp(-b(3)*x(:, 1));
beta0 = [10000, 300, 1]; % Guess values to start with. Just make your best guess.
% Now the next line is where the actual model computation is done.
mdl = fitnlm(tbl, modelfun, beta0);
% Now the model creation is done and the coefficients have been determined.
% YAY!!!!
% Extract the coefficient values from the the model object.
% The actual coefficients are in the "Estimate" column of the "Coefficients" table that's part of the mode.
coefficients = mdl.Coefficients{:, 'Estimate'}
% Create smoothed/regressed data using the model:
yFitted = coefficients(1) + coefficients(2) * exp(-coefficients(3)*X);
% Now we're done and we can plot the smooth model as a red line going through the noisy blue markers.
hold on;
plot(X, yFitted, 'k-', 'LineWidth', 3);
grid on;
title('Exponential Regression with fitnlm()', 'FontSize', fontSize);
xlabel('X', 'FontSize', fontSize);
ylabel('Y', 'FontSize', fontSize);
legendHandle = legend('Original Signal', 'Baseline', 'Fitted Y', 'Location', 'north');
legendHandle.FontSize = 25;
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
% Get rid of tool bar and pulldown menus that are along top of figure.
% set(gcf, 'Toolbar', 'none', 'Menu', 'none');
% Give a name to the title bar.
set(gcf, 'Name', 'Demo by ImageAnalyst', 'NumberTitle', 'Off')
The black line is the exponential fit of the bottoms of the signal.
  4 件のコメント
joshua marvin
joshua marvin 2025 年 2 月 20 日
Sorry this is on an old post but is there a way to get the model to be e^-x^2 it tells me to use .^2 but then it givs me not a number or inf errors
Image Analyst
Image Analyst 2025 年 2 月 20 日
@joshua marvin have the model be this:
modelfun = @(b,x) b(1) + b(2) * exp(-b(3)*x(:, 1) .^ 2);

サインインしてコメントする。


Image Analyst
Image Analyst 2018 年 5 月 16 日
Well you can try imerode() or movmin(). Or you can try some more sophisticated spectroscopic methods. It would have been easy for people to try things if you had attached your data. Try this link

カテゴリ

Help Center および File ExchangeMeasurements and Feature Extraction についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by