Butterworth filter for ecg signal in healthy people

106 次查看(过去 30 天)
Rp = 1; % passband ripple
Rs = 40; % stopband ripple
Fs = 5000; % sampling frequency
Fn = Fs/2; % nyquist frequency
Fpass = [0.05 150]; % passband
Fstop = [0.01 200]; % stopband
Wp = Fpass/Fn; % normalized
Ws = Fstop/Fn;
% Create a butterworth filter
[N,Wn] = buttord(Wp,Ws,Rp,Rs); % Returns the lowest order
[B,A] = butter(N,Wn); % Butterworth filter design
[sos1,g1] = tf2sos(B,A); % Convert digital filter transfer to second-order section form
ecg = filtfilt(sos1, g1, ecg_raw);
time = 1:length(ecg);
subplot(2,1,1)
plot(time,ecg_raw);
title('Raw ecg')
subplot(2,1,2)
plot(time,ecg)
title('Ecg filtered')
Hi.
Im trying to filter a ecg signal using a butterworth filter. Been looking a lot of postes trying to figure it out. Im new in signal in signal processing so it's possible that i dont fully understand the processing and the parametres which is required doing it.
can you point me the right direction?
  4 个评论
Mathieu NOE
Mathieu NOE 2021-4-28
hello
yes you can zip it
if it's very big maybe we can start to work on the problem on a smaller extract of the data
also at what sampling rate are you working ?
cheers
Christian Otte
Christian Otte 2021-4-28
I would love your input the signal processing.
It's is a ecg signal at a healthy person. It's sampled at 5000Hz across the heart.

请先登录,再进行评论。

采纳的回答

Star Strider
Star Strider 2021-4-27
The filter may be unstable, and if so, may not produce any output. Another possibility is that one or more of the elements of the data are NaN (although unlikely).
The best option is probably to use the bandpass function, specifically:
Fs = 5000;
Fpass = [1 100];
ecg = bandpass(ecg_raw, Fpass, Fs);
Although if there is no significant baselline wander, using a lowpass filter would work.
The signal appears to have a significant noise component, however it is not possible to determine what that is. The way to determine that is to calculate and plot the Fourier transform of the signal —
ecg_raw = data(:,3);
L = numel(ecg_raw);
time = linspace(0, L, L)/Fs;
N = 2^nextpow2(L);
FTs = fft(ecg_raw,N)/L;
Fv = linspace(0, 1, N/2+1)*Fn;
Iv = 1:numel(Fv);
figure
plot(Fv, abs(FTs(Iv))*2)
grid
If this is 50-60 Hz supply frequency noise, it can be eliminated with a notch filter (the bandstop function). If it is broadband noise, the only effective ways to deal with it are wavelet denoising or the Savitzky-Golay filter (the sgolayfilt function).
  6 个评论
Christian Otte
Christian Otte 2021-4-28
Thanks a lot. I works perfectly, also with another dataset. Besides, I can't see the variable Fn. But I guess it's based on Nyquist theory and therefore: Fn = Fs/2?
Also, figure 4, which look like it has no plot in it?
My only challenge now is that you delivered coding material at a whole other level than the university teachers prepared me fore :) I only have one more question. Is it possible that I can persuade you commenting each line of the code so I have a chance to do some research regarding how this filter works?
Star Strider
Star Strider 2021-4-28
I was in the middle of responding when Windows crashed. Again. (I really hate the current version of Windows!)
Anyway, since it is not possible to load .mat files in the online application that I now routinely use to run my code in my Answers and Comments, I downloaded the .mat file and ran it on this computer, offline. I initially forgot to copy the ‘Fn’ assignment, however it is now added where it should be.
The last ‘(Detail)’ figure is specifically for the provided data. Note that it has a xlim call at the end, and this is likely the reason a plot using a different data set is empty, since it may not contain the same x-axis values. (The last figure is not necessary for the code. It simply demonstrates that the FIR filter works even better than I though it would!)
The filter itself is straightforward. A detailed discussion of it is in the kaiserord documentation. Beyond that, it is simply a standard FIR filter with the advantage that it combines a highpass filter (eliminiating the baseline variation) and two stopband filters to eliminate the mains frequency interference and the first harmonic (the only one that appears to add significant noise). There are several excellent signal processing texts available that go into significant detail on all types of filters, of course including FIR filters. They discuss them in much more detail (and with significantly greater authority) than I could, so I refer you to them. Many are listed in the references section at the end of each documentation page.

请先登录,再进行评论。

更多回答(1 个)

Mathieu NOE
Mathieu NOE 2021-4-29
hello
dear all, an alternative using a 5th order IIR filter to remove the usual 50 Hz and harmonics mains hum
LD = load('ECG_sample.mat');
time_index = LD.time_index;
ecg_raw = time_index(:,2);
Fs = 5000;
Fn = Fs/2;
time = time_index(:,1)/Fs;
L = numel(ecg_raw);
N = 2^nextpow2(L);
FTs = fft(ecg_raw,N)/L;
Fv = linspace(0, 1, N/2+1)*Fn;
Iv = 1:numel(Fv);
figure
plot(Fv, abs(FTs(Iv))*2)
grid
title('Fourier Transform')
xlim([0 170])
%% two notch filters in series to remove 50 and 100 Hz hum
fc = 50; % notch freq for 50 Hz tone
Q = 7; % adjust Q factor for wider (low Q) / narrower (high Q) notch ; f = fc the filter has gain = 0
[B1,A1] = mynotchfilter(fc,Q, Fs);
fc = 2*50; % notch freq for 100 Hz tone
Q = 7; % adjust Q factor for wider (low Q) / narrower (high Q) notch ; f = fc the filter has gain = 0
[B2,A2] = mynotchfilter(fc,Q, Fs);
% two filter is series
B = conv(B1,B2);
A = conv(A1,A2);
ecg_filt = filtfilt(B, A, ecg_raw);
figure
freqz(B, A, 2^16, Fs)
figure
subplot(2,1,1)
plot(time, ecg_raw)
grid
title('Original Signal')
subplot(2,1,2)
plot(time, ecg_filt)
grid
title('Bandstop-Filtered Signal')
figure
subplot(2,1,1)
plot(time, ecg_raw)
grid
xlim([20 22])
title('Original Signal (Detail)')
subplot(2,1,2)
plot(time, ecg_filt)
grid
xlim([20 22])
title('Bandstop-Filtered Signal (Detail)')
function [B,A] = mynotchfilter(fc,Q, Fs)
%% notch filter section %%%%%%
% H(s) = (s^2 + 1) / (s^2 + s/Q + 1)
% fc = 50; % notch freq
wc = 2*pi*fc;
% Q = 7; % adjust Q factor for wider (low Q) / narrower (high Q) notch
% at f = fc the filter has gain = 0
w0 = 2*pi*fc/Fs;
alpha = sin(w0)/(2*Q);
b0 = 1;
b1 = -2*cos(w0);
b2 = 1;
a0 = 1 + alpha;
a1 = -2*cos(w0);
a2 = 1 - alpha;
B=[b0 b1 b2];
A=[a0 a1 a2];
end

类别

Help CenterFile Exchange 中查找有关 Multirate Signal Processing 的更多信息

产品


版本

R2021a

Community Treasure Hunt

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

Start Hunting!

Translated by