Diff of /DS_detect.m [000000] .. [e6b7a4]

Switch to unified view

a b/DS_detect.m
1
function [QRS_amp,QRS_ind] = DS_detect( ecg_i,gr )
2
%% function [QRS_amp,QRS_ind]=DS_detect(ecg_i,gr)
3
%% 输入
4
% ecg_i : 原信号,一维向量
5
% gr : 绘图与否,0:不绘图,1:绘图
6
%% 输出
7
% QRS_amp:QRS波振幅.
8
% QRS_ind:QRS波索引.
9
% 绘制图像.
10
%% 作者:刘文涵(WHliu@whu.edu.cn)
11
%% 版本:1.1
12
%% 04-24-2018
13
%% 代码:
14
if nargin < 2
15
    gr = 1; 
16
    if nargin<1
17
           error('The algorithm need a input:ecg_i.');
18
    end
19
end
20
if ~isvector(ecg_i)
21
  error('ecg_i must be a row or column vector.');
22
end
23
fs=360;
24
if size(ecg_i,2)<round(1.5*fs)+1
25
    error('The algorithm need a longer input.');
26
end
27
tic,
28
s=ecg_i;
29
N=size(s,2);
30
ECG=s;
31
FIR_c1=[0.0041,0.0053,0.0068,0.0080,0.0081,0.0058,-0.0000,-0.0097,-0.0226,...   
32
   -0.0370,-0.0498,-0.0577,-0.0576,-0.0477,-0.0278,0,0.0318,0.0625,0.0867,...    
33
    0.1000,0.1000,0.0867,0.0625,0.0318,0,-0.0278,-0.0477,-0.0576,-0.0577,...   
34
    -0.0498,-0.0370,-0.0226,-0.0097,-0.0000,0.0058,0.0081,0.0080,0.0068,...
35
    0.0053,0.0041]; % 使用fdatool设计并导出的滤波器系数,带通FIR,15~25Hz,详情使用fdatool打开DS1.fda查看
36
FIR_c2=[0.0070,0.0094,0.0162,0.0269,0.0405,0.0555,0.0703,0.0833,0.0928,...    
37
    0.0979,0.0979,0.0928,0.0833,0.0703,0.0555,0.0405,0.0269,0.0162,0.0094,...    
38
    0.0070]; % 使用fdatool设计并导出的滤波器系数,低通FIR,截止频率5Hz,详情使用fdatool打开DS2.fda查看
39
40
l1=size(FIR_c1,2);
41
ECG_l=[ones(1,l1)*ECG(1) ECG ones(1,l1)*ECG(N)]; % 数据点延拓,防止滤波边缘效应;
42
ECG=filter(FIR_c1,1,ECG_l); % 使用filter滤波;
43
ECG=ECG((l1+1):(N+l1)); % 前面延拓了数据点,这里截取有用的部分;
44
45
%% 双斜率处理
46
a=round(0.015*fs);  % 两侧目标区间0.015~0.060s;
47
b=round(0.060*fs);
48
Ns=N-2*b;           % 确保在不超过信号长度;
49
S_l=zeros(1,b-a+1);
50
S_r=zeros(1,b-a+1);
51
S_dmax=zeros(1,Ns);
52
for i=1:Ns          % 对每个点双斜率处理;
53
    for k=a:b
54
        S_l(k-a+1)=(ECG(i+b)-ECG(i+b-k))./k;
55
        S_r(k-a+1)=(ECG(i+b)-ECG(i+b+k))./k;
56
    end
57
  S_lmax=max(S_l);
58
  S_lmin=min(S_l);
59
  S_rmax=max(S_r);
60
  S_rmin=min(S_r);
61
  C1=S_rmax-S_lmin;
62
  C2=S_lmax-S_rmin;
63
  S_dmax(i)=max([C1 C2]);
64
end
65
66
%% 再次进行低通滤波,思路与上述带通滤波一致
67
l2=size(FIR_c2,2);
68
S_dmaxl=[ones(1,l2)*S_dmax(1) S_dmax ones(1,l2)*S_dmax(Ns)];
69
S_dmaxt=filter(FIR_c2,1,S_dmaxl);
70
S_dmaxt=S_dmaxt((l2+1):(Ns+l2));
71
72
%% 滑动窗口积分
73
w=8;wd=7;
74
d_l=[zeros(1,w) S_dmaxt zeros(1,w)];  % 零延拓,确保所有的点都可以进行窗口积分
75
m=zeros(1,Ns);
76
   for n=(w+1):(Ns+w)                 % 滑动窗口;
77
      m(n-w)=sum(d_l(n-w:n+w));       % 积分;
78
   end
79
m_l=[ones(1,wd)*m(1) m ones(1,wd)*m(Ns)]; 
80
81
%% 双阈值检测与动态变化
82
QRS_buf1=[];   % 存储检测到的QRS波索引
83
AMP_buf1=[];   % 存储最近检测到的8个QRS波对应特征信号的波峰值
84
thr_init0=0.4;thr_lim0=0.23;
85
thr_init1=0.6;thr_lim1=0.3;  %% 阈值变化的初始值和下限设置
86
en=-1;        % 标记波峰检出情况,高于高阈值--1,高低阈值之间--0,未检出-- -1
87
thr0=thr_init0;
88
thr1=thr_init1;
89
thr1_buf=[]; % 阈值缓存,记录阈值变化情况;
90
thr0_buf=[];
91
for j=8:Ns
92
       t=1;
93
       cri=1;
94
       while t<=wd&&cri>0   % 检测候选波峰;
95
           cri=((m_l(j)-m_l(j-t))>0)&&(m_l(j)-m_l(j+t)>0);
96
           t=t+1;
97
       end
98
       if t==wd+1
99
           N1=size(QRS_buf1,2);               %N1:已经检测到的QRS波个数
100
           if m_l(j)>thr1                     % 高于高阈值时的处理
101
               if N1<2                        % N1小于2时直接存储;
102
                 QRS_buf1=[QRS_buf1 (j-wd)];  % j-wd 减去了滑动窗口积分带来的延迟;
103
                 AMP_buf1=[AMP_buf1 m_l(j)];
104
                 en=1;
105
               else
106
                 dist=j-wd-QRS_buf1(N1);
107
                 if dist>0.24*fs               % 检测波峰距离;
108
                     QRS_buf1=[QRS_buf1 (j-wd)]; 
109
                     AMP_buf1=[AMP_buf1 m_l(j)];
110
                     en=1;
111
                 else
112
                     if m_l(j)>AMP_buf1(end)   % 不应期处理
113
                         QRS_buf1(end)=j-wd;
114
                         AMP_buf1(end)=m_l(j);
115
                         en=1;
116
                     end     
117
                 end
118
               end
119
     
120
          else                                 % 特征峰值低于高阈值
121
               
122
              if N1<2&&m_l(j)>thr0             % 特征峰值在两阈值之间
123
                  QRS_buf1=[QRS_buf1 (j-wd)];
124
                  AMP_buf1=[AMP_buf1 m_l(j)];
125
                  en=0;
126
              else
127
                if m_l(j)>thr0                 % 特征峰值在两阈值之间
128
                  dist_m=mean(diff(QRS_buf1));
129
                  dist=j-wd-QRS_buf1(N1);
130
                  if dist>0.24*fs && dist>0.5*dist_m  % 不应期检测,并且,波峰要距离足够远(> 平均距离的一半)
131
                     QRS_buf1=[QRS_buf1 (j-wd)];
132
                     AMP_buf1=[AMP_buf1 m_l(j)];
133
                     en=0;
134
                  else
135
                      if m_l(j)>AMP_buf1(end)
136
                         QRS_buf1(end)=j-wd;
137
                         AMP_buf1(end)=m_l(j);
138
                         en=0;
139
                      end 
140
                  end
141
                else
142
                    en=-1;
143
                end
144
              end
145
           end
146
           N2=size(AMP_buf1,2);
147
           if N2>8
148
               AMP_buf1=AMP_buf1(2:9); % 确保只存储最近的8个特征波峰;
149
           end
150
           % 下面的if与博文中的公式对应
151
           if en==1
152
              thr1=0.7*mean(AMP_buf1);
153
              thr0=0.25*mean(AMP_buf1);
154
           else
155
               if en==0
156
                   thr1=thr1-(abs(m_l(j)-mean(AMP_buf1)))/2;
157
                   thr0=0.4*m_l(j);
158
               end
159
           end
160
       end
161
       if thr1<=thr_lim1   % 确保阈值高于下限
162
           thr1=thr_lim1;
163
       end
164
       
165
       if thr0<=thr_lim0
166
           thr0=thr_lim0;
167
       end
168
       
169
      thr1_buf=[thr1_buf thr1]; 
170
      thr0_buf=[thr0_buf thr0];
171
end
172
delay=round(l1/2)-2*w+2;
173
QRS_ind=QRS_buf1-delay;   % 减去延迟,得到最终结果;
174
QRS_amp=s(QRS_ind);
175
toc
176
if gr==1    %绘图
177
   subplot(2,1,1);plot(m);axis([1 size(m,2) -0.3 1.6*max(m)]);
178
   hold on;title('Feature signal and thresholds');grid on;
179
   plot(QRS_buf1,m(QRS_buf1),'ro');
180
   plot(thr1_buf,'r');
181
   plot(thr0_buf,'k');
182
   legend('Feature Signal','QRS Locations','Threshold1','Threshold0');
183
   subplot(2,1,2);plot(s);%axis([1 size(s,2) min(s) 1.5*max(s)]);
184
   xlabel('n');ylabel('Voltage / mV');
185
   hold on;title('The result on the raw ECG');grid on;
186
   plot(QRS_ind,QRS_amp,'ro');
187
   legend('Raw ECG','QRS Locations');
188
end
189
end
190