MIT-BIH公开数据集下载地址如下:
MIT-BIH Arrhythmia Database v1.0.0 (physionet.org)https://www.physionet.org/content/mitdb/1.0.0/可以知道,心电数据的储存通常通过三个类型的文件,详解参考:
matlab代码如下:
国外大神原创(具体叫啥得回来找找- -),可以读取三个类型文件
clc; clear all;
%------ SPECIFY DATA ------------------------------------------------------
%%选择文件名称
stringname='111';
%选择你要处理的信号点数
points=10000;
PATH= 'F:\ECG\MIT-BIH database directory'; % path, where data are saved
HEADERFILE= strcat(stringname,'.hea'); % header-file in text format
ATRFILE= strcat(stringname,'.atr'); % attributes-file in binary format
DATAFILE=strcat(stringname,'.dat'); % data-file
SAMPLES2READ=points; % number of samples to be read
% in case of more than one signal:
% 2*SAMPLES2READ samples are read
%------ LOAD HEADER DATA --------------------------------------------------
fprintf(1,'\\n$> WORKING ON %s ...\n', HEADERFILE);
signalh= fullfile(PATH, HEADERFILE);
fid1=fopen(signalh,'r');
z= fgetl(fid1);
A= sscanf(z, '%*s %d %d %d',[1,3]);
nosig= A(1); % number of signals
sfreq=A(2); % sample rate of data
clear A;
for k=1:nosig
z= fgetl(fid1);
A= sscanf(z, '%*s %d %d %d %d %d',[1,5]);
dformat(k)= A(1); % format; here only 212 is allowed
gain(k)= A(2); % number of integers per mV
bitres(k)= A(3); % bitresolution
zerovalue(k)= A(4); % integer value of ECG zero point
firstvalue(k)= A(5); % first integer value of signal (to test for errors)
end;
fclose(fid1);
clear A;
%------ LOAD BINARY DATA --------------------------------------------------
if dformat~= [212,212], error('this script does not apply binary formats different to 212.'); end;
signald= fullfile(PATH, DATAFILE); % data in format 212
fid2=fopen(signald,'r');
A= fread(fid2, [3, SAMPLES2READ], 'uint8')'; % matrix with 3 rows, each 8 bits long, = 2*12bit
fclose(fid2);
M2H= bitshift(A(:,2), -4);
M1H= bitand(A(:,2), 15);
PRL=bitshift(bitand(A(:,2),8),9); % sign-bit
PRR=bitshift(bitand(A(:,2),128),5); % sign-bit
M( : , 1)= bitshift(M1H,8)+ A(:,1)-PRL;
M( : , 2)= bitshift(M2H,8)+ A(:,3)-PRR;
if M(1,:) ~= firstvalue, error('inconsistency in the first bit values'); end;
switch nosig
case 2
M( : , 1)= (M( : , 1)- zerovalue(1))/gain(1);
M( : , 2)= (M( : , 2)- zerovalue(2))/gain(2);
TIME=(0:(SAMPLES2READ-1))/sfreq;
case 1
M( : , 1)= (M( : , 1)- zerovalue(1));
M( : , 2)= (M( : , 2)- zerovalue(1));
M=M';
M(1)=[];
sM=size(M);
sM=sM(2)+1;
M(sM)=0;
M=M';
M=M/gain(1);
TIME=(0:2*(SAMPLES2READ)-1)/sfreq;
otherwise % this case did not appear up to now!
% here M has to be sorted!!!
disp('Sorting algorithm for more than 2 signals not programmed yet!');
end;
clear A M1H M2H PRR PRL;
fprintf(1,'\\n$> LOADING DATA FINISHED \n');
%------ LOAD ATTRIBUTES DATA ----------------------------------------------
atrd= fullfile(PATH, ATRFILE); % attribute file with annotation data
fid3=fopen(atrd,'r');
A= fread(fid3, [2, inf], 'uint8')';
fclose(fid3);
ATRTIME=[];
ANNOT=[];
sa=size(A);
saa=sa(1);
i=1;
while i<=saa
annoth=bitshift(A(i,2),-2);
if annoth==59
ANNOT=[ANNOT;bitshift(A(i+3,2),-2)];
ATRTIME=[ATRTIME;A(i+2,1)+bitshift(A(i+2,2),8)+...
bitshift(A(i+1,1),16)+bitshift(A(i+1,2),24)];
i=i+3;
elseif annoth==60
% nothing to do!
elseif annoth==61
% nothing to do!
elseif annoth==62
% nothing to do!
elseif annoth==63
hilfe=bitshift(bitand(A(i,2),3),8)+A(i,1);
hilfe=hilfe+mod(hilfe,2);
i=i+hilfe/2;
else
ATRTIME=[ATRTIME;bitshift(bitand(A(i,2),3),8)+A(i,1)];
ANNOT=[ANNOT;bitshift(A(i,2),-2)];
end;
i=i+1;
end;
ANNOT(length(ANNOT))=[]; % last line = EOF (=0)
ATRTIME(length(ATRTIME))=[]; % last line = EOF
clear A;
ATRTIME= (cumsum(ATRTIME))/sfreq;
ind= find(ATRTIME <= TIME(end));
ATRTIMED= ATRTIME(ind);
ANNOT=round(ANNOT);
ANNOTD= ANNOT(ind);
%------ DISPLAY DATA ------------------------------------------------------
figure(1); clf, box on, hold on ;grid on ;
plot(TIME, M(:,1),'r');
if nosig==2
plot(TIME, M(:,2),'b');
end;
for k=1:length(ATRTIMED)
text(ATRTIMED(k),0,num2str(ANNOTD(k)));
end;
xlim([TIME(1), TIME(end)]);
xlabel('Time / s'); ylabel('Voltage / mV');
string=['ECG signal ',DATAFILE];
title(string);
fprintf(1,'\\n$> DISPLAYING DATA FINISHED \n');
% -------------------------------------------------------------------------
fprintf(1,'\\n$> ALL FINISHED \n');
python代码如下:
##################################################
import numpy as np
import matplotlib.pyplot as plt
PATH="./MIT-BIH/" #path, 这里就是写刚才你保存的数据地址
HEADERFILE="105.hea" #文件格式为文本格式
ATRFILE="105.atr" #attributes-file 文件以二进制格式
DATAFILE="105.dat" #data-file
SAMPLES2READ=3000 #读取的数据样本点数
####################读取头文件######################
f=open(PATH+HEADERFILE,"r")
z=f.readline().split()
nosig,sfreq=int(z[1]),int(z[2]) #% number of signals,sample rate of data
dformat,gain,bitres,zerovalue,firstvalue=[],[],[],[],[]
for i in range(nosig):
z=f.readline().split()
dformat.append(int(z[1])) #format; here only 212 is allowed
gain.append(int(z[2])) #number of integers per mV
bitres.append(int(z[3])) #bitresolution
zerovalue.append(int(z[4])) #integer value of ECG zero point
firstvalue.append(int(z[5])) #first integer value of signal (to test for errors)
f.close()
####################读取dat文件######################
f=open(PATH+DATAFILE,"rb") #以二进制格式读入dat文件
b=f.read()
f.close()
A_init=np.frombuffer(b,dtype=np.uint8) #将读入的二进制文件转化为unit8格式
A_shape0=int(A_init.shape[0]/3)
A=A_init.reshape(A_shape0,3)[:SAMPLES2READ] #将A转为3列矩阵
M=np.zeros((SAMPLES2READ,2)) #创建矩阵M
M2H=A[:,1]>>4 #字节向右移四位,即取字节的高四位
M1H=A[:,1]&15 #取字节的低四位
PRL=(A[:,1]&8)*(2**9) #sign-bit 取出字节低四位中最高位,向左移九位,等于乘2^9
PRR=A[:,1]&128<<5 #sign-bit 取出字节高四位中最高位,向左移五位
M1H=M1H*(2**8)
M2H=M2H*(2**8)
M[:,0]=A[:,0]+M1H-PRL
M[:,1]=A[:,2]+M2H-PRR
if ((M[1,:]!=firstvalue).any()):
print("inconsistency in the first bit values")
if nosig==2:
M[:, 0] = (M[:, 0] - zerovalue[0]) / gain[0]
M[:, 1] = (M[:, 1] - zerovalue[1]) / gain[1]
TIME=np.linspace(0,SAMPLES2READ-1,SAMPLES2READ)/sfreq
elif nosig==1:
M2=[]
M[:, 0] = M[:, 0] - zerovalue[0]
M[:, 1] = M[:, 1] - zerovalue[1]
for i in range(M.shape[0]):
M2.append(M[:,0][i])
M2.append(M[:,1][i])
M2.append(0)
del M2[0]
M2=np.array(M2)/gain[0]
TIME=np.linspace(0,2*SAMPLES2READ-1,2*SAMPLES2READ)/sfreq
else:
print("Sorting algorithm for more than 2 signals not programmed yet!")
####################读取atr文件######################
f=open(PATH+ATRFILE,"rb") #主要是读取ATR文件中各周期数据并在之后打印在图中
b=f.read()
f.close()
A_init=np.frombuffer(b,dtype=np.uint8)
A_shape0=int(A_init.shape[0]/2)
A=A_init.reshape(A_shape0,2)
ANNOT,ATRTIME=[],[]
i=0
while i < A.shape[0]:
annoth=A[i,1]>>2
if annoth==59:
ANNOT.append(A[i+3,1]>>2)
ATRTIME.append(A[i+2,0]+A[i+2,1]*(2**8)+A[i+1,0]*(2**16)+A[i+1,1]*(2**24))
i+=3
elif annoth==60:pass
elif annoth==61:pass
elif annoth==62:pass
elif annoth==63:
hilfe=(A[i,1]&3)*(2**8)+A[i,0]
hilfe=hilfe+hilfe%2
i+=int(hilfe/2)
else:
ATRTIME.append((A[i,1]&3)*(2**8)+A[i,0])
ANNOT.append(A[i,1]>>2)
i+=1
del ANNOT[len(ANNOT)-1]
del ATRTIME[len(ATRTIME)-1]
ATRTIME=np.array(ATRTIME)
ATRTIME=np.cumsum(ATRTIME)/sfreq
ind=np.where(ATRTIME<=TIME[-1])[0]
ATRTIMED=ATRTIME[ind]
ANNOT=np.round(ANNOT)
ANNOTD=ANNOT[ind]
#####################显示ECG####################
plt.plot(TIME,M[:,0],linewidth="0.5",c="r")
if nosig==2:
plt.plot(TIME, M[:, 1], linewidth="0.5", c="b")
for i in range(len(ATRTIMED)):
plt.text(ATRTIMED[i],0,str(ANNOTD[i]))
plt.xlim(TIME[0],TIME[-1])
plt.xlabel("Time / s")
plt.ylabel("Votage / mV")
plt.title("ECG signal ")
plt.show()
python补充解释版参考:
然鹅,python有一个wfdb的包,可以专门用来读取心电信号233
好的没关系,我们弄懂一些ECG的原理也是好的。
下面开始介绍这个wfdb的包及用法,参考,继续整理:
感谢参考: