✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。
🍎个人主页:Matlab科研工作室
🍊个人信条:格物致知。
更多Matlab仿真内容点击👇
⛄ 内容介绍
从原始心电图信号中去除不一致和尖峰,并将心电信号分离为P波、QRS波和T波是心电信号处理的关键步骤。下面是一个基本的处理框架:
-
去噪:使用数字滤波技术,例如低通滤波器或中值滤波器,去除原始心电图信号中的高频噪声和不一致成分。这有助于平滑信号并减少突发尖峰。
-
R波检测:应用R波检测算法来定位QRS波群的峰值。这可以使用峰值检测、阈值检测或相关方法等进行实现。R波处于QRS复合波的最高点。
-
分割:基于R波的位置,将QRS复合波从原始心电图信号中分割出来,以获得每个心搏的独立波形。
-
P波和T波分离:在QRS波形区域之外,使用特定方法(如滑动窗口平均或自适应阈值)识别和提取P波和T波。P波位于QRS波群之前,而T波位于QRS波群之后。
需要注意的是,心电信号处理是一个复杂且具有挑战性的程,可能涉及到信号噪声、基线干扰、不一致理现象等多个方面的问题。因此,为了获得准心电波形分离和去除尖峰,可能需要结合更高级的信号处理技术和机器学习算法。
⛄ 部分代码
function [data_extracted,average_heart_beat_rate] = ECG_Anormaly_Detection_Algorithm(ECG_data,Fs,ECG_distance_threshold_sensivity,ECG_peak_sensivity)
if (nargin<3)
%these thresholds are used to choose ECG segments that are most similar to each other.
%the more the value, the more ECG segments'similarity it takes
ECG_distance_threshold_sensivity=5; % threshold for finding ECG signal by the distance difference
ECG_peak_sensivity=35; % threshold for finding ECG signal by the peak differences
end
format long
BL=[1 zeros(1,5) -2 zeros(1,5) 1];
AL=[32,-64,32];
BH=[-1 zeros(1,15) 32 -32 zeros(1,14) 1];
AH=[32 -32];
AINT=[8];
BINT=[2 1 0 -1 -2 ];
BMOV=ones(1,30)./30;
AMOV=[1];
min_distance=(Fs/2)-round(Fs/6);
[preB,preA]=butter(4,[2/Fs 60/Fs]);
y=filtfilt(preB,preA,ECG_data);
yL=filter(BL,AL,y);
yH=filter(BH,AH,yL);
yder=filter(BINT,AINT,yH);
yder=filter(BINT,AINT,yH);
ysqu=yder.^2;
yaov=filter(BMOV,AMOV,ysqu);
[pks,locs]=findpeaks(yaov,'MinPeakDistance',Fs);
ECG_range=median(pks)+median(pks)/ECG_distance_threshold_sensivity;
if(max(pks>=ECG_range))
pks= pks(~(pks>=ECG_range));
locs=locs(~(pks>=ECG_range));
end
Threshold=max(pks)*ECG_peak_sensivity/100;
clear pks locs
[pks,locs]=findpeaks(yaov,'MinPeakHeight',Threshold,'MinPeakDistance',min_distance);
new_locs=zeros([size(locs)]);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%The value 23 is the group delay of Pan-Tompkins filters.
%It is used to match the original ECG signals with the R points found by using output of Pan-Tompkins filters
group_delay=23;
if(locs(1,1)>round(Fs/group_delay))
new_locs=locs-round(Fs/group_delay);
else
new_locs=locs(2:end)-round(Fs/group_delay);
pks=pks(2:end);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for i=1:length(new_locs)
if(new_locs(i)>(Fs/2) && new_locs(i)+(Fs/2)<length(yaov))
X=yaov(new_locs(i)-(Fs/2):new_locs(i)+(Fs/2));
X=ECG_data(new_locs(i)-(Fs/2):new_locs(i)+(Fs/2));
else
X=0;
end
mu=mean(X);
sigma(i) = std(X)-mu;
clear X
end
ECG_signal_ortalama=median(sigma);
Threshold_ECG_Signal=(ECG_signal_ortalama/ECG_distance_threshold_sensivity);
%Erase the signal locations
locs_remove=[];
j=1;
z=1;
locs2=0;
for i=1:length(sigma)
if((ECG_signal_ortalama+Threshold_ECG_Signal)<sigma(i)||(ECG_signal_ortalama-Threshold_ECG_Signal)>sigma(i))
locs_remove(j)=new_locs(i);
j=j+1;
else
locs2(z)=new_locs(i);
z=z+1;
end
end
clear z
average=0;
for i=1:length(locs2)-1
average=average+abs(locs2(i)-locs2(i+1));
end
average_heart_beat_rate=(Fs/(average/(length(locs2))))*60;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Double Check if there is anything unusual between two R points
start=1;
range=0;
data_extracted{1}=0;
for i=2:length(locs2)
range=range+abs(locs2(i-1)-locs2(i));
end
range=range/length(locs2);
Threshols_ayrim_h=range+range/(ECG_distance_threshold_sensivity/2);
Threshols_ayrim_l=range-range/(ECG_distance_threshold_sensivity/2);
for i=2:length(locs2)
X(i)=std(ECG_data(locs2(i-1):locs2(i)))-mean(ECG_data(locs2(i-1):locs2(i)));
end
if(length(locs2)==1)
X=0;
end
Threshols_ayrim_2h=abs(median(X)+median(X)/(ECG_distance_threshold_sensivity/1));
Threshols_ayrim_2l=abs(median(X)-median(X)/(ECG_distance_threshold_sensivity/1));
k=1;
i=2;
first_index=1;
while i<=length(locs2)
sigma1=std(ECG_data(locs2(i-1):locs2(i)))-mean(ECG_data(locs2(i-1):locs2(i)));
if(((abs(locs2(i-1)-locs2(i))>=Threshols_ayrim_h)||((abs(locs2(i-1)-locs2(i))<=Threshols_ayrim_l)))||((sigma1>=Threshols_ayrim_2h)||(sigma1<=Threshols_ayrim_2l)))
if(start==1)
clear data_extracted
start=0;
end
if(~(abs(locs2(first_index)-locs2(i-1))<=Fs*2))
data_extracted{k}(:)=ECG_data(locs2(first_index):locs2(i-1));
k=k+1;
end
first_index=i;
end
i=i+1;
end
if((start==1 || (first_index~=1 && start==0))&& (length(locs2)~=1))
if(start==1)
clear data_extracted
end
data_extracted{k}(:)=ECG_data(locs2(first_index):locs2(i-1));
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figo=figure('WindowState','maximized');
plot(0:1/Fs:length(ECG_data)/Fs-1/Fs,ECG_data)
hold on
if(length(locs2)~=1)
plot(locs2/Fs,(ECG_data(locs2)),'o','MarkerSize',6)
end
pos = get(figo,'position');
set(figo,'position',[pos(1:2)/4 pos(3:4)*1.5]);
set(gca,'Fontsize',16)
title('Raw ECG Signal','fontsize',32);
hold off
xlabel('Time in Seconds','fontsize',24);
ylabel('12 bits Raw ECG','fontsize',24);
end
⛄ 运行结果
⛄ 参考文献
Guven, Gokhan, et al. “A Novel Biometric Identification System Based on Fingertip Electrocardiogram and Speech Signals.” Digital Signal Processing, vol. 121, Elsevier BV, Mar. 2022, p. 103306, doi:10.1016/j.dsp.2021.103306.