zoukankan      html  css  js  c++  java
  • MIT-HIB 心率数据库及相关

    基于机器学习的心律失常分类(二)——读取MIT-BIH数据库中的心电数据[MATLAB]

    基于机器学习的心律失常分类(二)——读取MIT-BIH数据库中的心电数据[MATLAB]

     

    在上一篇文章中介绍了心电信号的一些基本理论,本篇文章将着重介绍什么是MIT-BIH数据库,以及如何获取、读取MIT-BIH心律失常数据库中的心电数据。

    我刚开始接触的时候特别迷茫,看了很多帖子才搞清楚。这篇绝对良心靠谱细致!!!

    一、MIT-BIH心律失常数据库

    目前有三个得到国际认可的心电数据库可以被用作临床标准,分别是由美国麻省理工学院提供的MIT-BIH心律失常数据库,美国心脏学会的AHA数据库以及欧洲ST-T心电数据库。其中,MIT-BIH数据库拥有大量数据并且有权威专家对其进行了详细的注释和标记,在对心律失常分类和临床研究中应用最为广泛。因此,本文的使用标准的MIT-BIH数据库的心电数据,并通过与权威专家提供的注释进行比较来分析和评估实验取得的结果。

    该数据库包括47个测试个体单位的4000多个24小时的周期性动态心电数据,有48个时长约为30min的记录文件,共计109500个心拍,其中异常心拍约占30%。MIT-BIH数据库中包含的心电记录文件共有三种类型。

    (1)头文件(.hea):记录文件中的头文件中的信息包括各个记录的所有数据的相关属性信息。包括采样频率,导联号,数据格式,分辨率,ADC,年龄等。

    (2)数据文件(.dat):数据文件统一采用了“212”数据存储模式,每一个数据文件有两个导联的信号数据。

    (3)注释文件(.art):注释文件中有权威专家标注的心拍类型与R波位置,为后面算法验证其有效性提供了依据。

    数据库对不同的心律失常类型做了统一命名,如下表所示。本文主要分析正常心电(N)、左束支阻滞(L)、右束支阻滞(R)及室性早搏(V)四种心拍类型。

    心律失常注释

     

    二、如何获取MIT-BIH的数据

    开源数据网站PhysioNet()提供了诸如MIMIC、MIT-BIH等丰富的生理信号数据库。

    获取MIT-BIH数据库数据,可以使用提供的PhysioBank ATM (PhysioBank ATM),在线地显示选定的数据,并将数据保存为txt或其他的形式。

    PhysioBank ATM 数据显示器网址示意图
    1. 在Database下拉框中选择MIT-BIH Arrhythmia Database(mitdb):
    Database下拉框中选择mitdb

    2. 简单介绍下各字段含义及下载方式

    MIT-BIH数据显示器

    1>Input

    (1)Database:所选取的数据库,我们已经选择了MIT-BIH心律失常数据库;

    (2)Record:文件编号,mitbih数据库一共有48个不同编号的文件,每一个编号分别对应一个个体的采集数据;

    (3)Singals:每个数据文件呢包括两个导联数据,通俗一点就是对每一个个体采集心电数据时用了两种方式,然后都给记录下来,可以选择使用其中一种方式,也可以都使用;

    (4)Annotations:就是指注释。

    2>Output

    (5)Length:默认的数据显示长度为10s,用户也可以选择1min、1hour显示,我下载的 是一个小时的;

    (6)Time format:时间格式,看个人需要那种查看,一般默认第一个就好了;

    (7)Data format:资料格式,一般默认第一个标准就好了。

    3>Toolbox

    MIT-BIH数据显示器 Toolbox

    共13个选项,比如选择在plot waveforms,就是直接在显示器中绘制数据波形。在显示的过程中可以点击下面的进度条,选择显示的区间。10s的心电数据显示如下:

    但是针对我们要对数据进行分析处理下载数据文件来说,要选择“Make zip file of record”,就可以得到如下图所示的下载地址,点击100.zip就可以下载编号100的数据文件了,然后可以继续下载其它编号的文件。

    编号100的下载地址
    因为我是用matlab来分别处理.hea/.dat/.art这三个数据,所以我下载的zip压缩包。但如果你想直接对txt或者mat文件进行处理,也可以选择相应的下载方式~看个人需求,我就按照我自己使用的来说啦

    3. 下载完成的数据文件

    下载并解压后的

    三、如何读取MIT-BIH的数据

    本文是使用MATLAB编程工具对三种文件进行读取处理的,一个一个来说。

    1. 头文件(.hea)

    以记录100的头文件100.hea为例进行说明,其文件内容如下:

    100.hea头文件内容
    该头文件的第一行为记录行,指出该记录为一包含两个采样率为360 Hz的信号,每一信号的长度为65万个采样点,采样开始时间和日期没有记录。后面紧跟的两行为信号技术规范说明行,从中可以看出,两个导联信号都包含在文件100.dat 中,每一信号都是以12位的位压缩格式(即“212”格式)进行存储的,两个信号的增益都是每200ADC units/mV ,ADC的分辨率为11位.ADC零值为1024,在这里基线值没有明确给出,但可以认为它等于ADC零值1024。两个信号的第一采样点的值分别为995和1011 (可以看出这他们都略低于0 V),65万个采样点的校验数分别为-22131和20052 ,输人输出可以以任何尺寸的块来执行,因为文件内容说明了这两个信号的该值都为0,信号描述字段说明了这两个信号分别采自MLII 导联和V5导联。文件的最后两行包含了注释字符串,其中第一行说明了患者的性别和年龄以及记录数据,第二行列出了患者的用药情况。

    上面一大段介绍了一下内容含义,那么如何用matlab将这些内容读取出来呢,就需要根据存储格式来读取,直接放代码吧~

    PATH= 'C:UserscccDesktop\数据1_源数据mit-bih-arrhythmia-database-1.0.0';  %数据文件所在文件夹地址
    HEADERFILE= '100.hea';   %选择记录编号
    % 通过函数 fullfile 获得头文件的完整路径
    signalh= fullfile(PATH, HEADERFILE);
    % 打开头文件,其标识符为 fid1 ,属性为'r'--“只读”
    fid1=fopen(signalh,'r');
    % 读取头文件的第一行数据,字符串格式
    z= fgetl(fid1);
    % 按照格式 '%*s %d %d %d' 转换数据并存入矩阵 A 中
    A= sscanf(z, '%*s %d %d %d',[1,3]);
    
    nosig= A(1);    % 信号通道数目
    sfreq=A(2);     % 数据采样频率
    SAMPLES2READ = 10*sfreq;    %取十秒数据
    
    for k=1:nosig           % 读取每个通道信号的数据信息
        z= fgetl(fid1);
        A= sscanf(z, '%*s %d %d %d %d %d',[1,5]);
        dformat(k)= A(1);       % 信号格式; 这里只允许为 212 格式
        gain(k)= A(2);          % 每 mV 包含的整数个数
        bitres(k)= A(3);        % 采样精度(位分辨率)
        zerovalue(k)= A(4);     % ECG 信号零点相应的整数值
        firstvalue(k)= A(5);    % 信号的第一个整数值 (用于偏差测试)
    end;
    fclose(fid1);
    clear A;

    以上就可以读取出头文件的内容了。

    2. 数据文件(.dat)

    MIT-BIH数据库中数据存储格式有Format 8、Format 16、Format 212、Format 310等8种,会在头文件中进行说明。最常用的就是212,是针对两个导联信号的数据记录。

    为了方便,将两个导联信号设定为信号0和信号1。格式212存储中,这两个信号交替存储,每三个字节存储两个数据,这两个数据分别来自信号0和信号1,信号0的采样数据取自第一字节对(共16位)的最低12位,信号1的采样数据由第一字节对的剩余4位(作为组成信号1采样数据的12位的高4位)和下一字节的8位(作为组成信号1采样数据的12位的低8位)共同组成。
    100.dat十六进制显示(片段)
    按照“212"的格式,从第一字节读起,每三个字节(24位)表示两个值,,第一组为“E3 33 F3",两个值则分别为0x3E3和0x3F3,转换为十进制分别为995和1011,代表的信号幅度分别为4.975mV和5.055 mV,这两个值分别是两个信号的第一采样点,后面依此类推,分别表示了两个信号的采样值。

    使用MATLAB读取数据文件:

    PATH= 'C:UserscccDesktop\数据1_源数据mit-bih-arrhythmia-database-1.0.0';  %数据文件所在文件夹地址
    DATAFILE='100.dat';  %选择记录编号
    %.dat文件的数据格式读取为每行三个字节,即三个八位的二进制数字,其内容含义为
    %      0000 0000  ||             0000 0000              ||  0000 0000
    %sign1(L)低八位信息||左四位sign2(R)信息,右四位sign1(L)信息||sign2(R)低八位信息
    %将第二字节的信息处理后,后四位移至第一字节最左位即得到完整的sign1
    %将第二字节的信息处理后,前四位移至第一字节最左位即得到完整的sign2.
    signald = fullfile(PATH , DATAFILE);
    fid2 = fopen(signald,'r');
    A= fread(fid2, [3, SAMPLES2READ], 'uint8')';
    fclose(fid2);
    
    %对第二字节做左位移运算,位移距离-4
    %得到第二字节左四位,即sign2的高四位,包括符号位,右高信息
    M_R_H = bitshift(A(:,2), -4);
    %对第二字节和1111做与运算,
    %保留第二字节右四位,即sign1的低四位,包括符号位,左高信息
    M_L_H = bitand(A(:,2), 15);
    %对第二字节和1000做与运算,
    %保留第二字节右边第四位,获取sign2符号位,并向左位移九位,与整体sign1进行运算
    PRL=bitshift(bitand(A(:,2),8),9); 
    %对第二字节和10000000做与运算,
    %保留第二字节右边第四位,获取sign1符号位,并向左位移5位,与整体sign2进行运算
    PRR=bitshift(bitand(A(:,2),128),5);
    
    %M矩阵为sign1,2的存储矩阵,存储100.dat处理后数据
    %将sign1(L)高位移至sign1低位前(A(:,1))
    %将sign2(R)高位移至sign2低位前(A(:,3))
    %最后将信号符号位信息去掉
    M( : , 1)= bitshift(M_L_H,8)+ A(:,1)-PRL;
    M( : , 2)= bitshift(M_R_H,8)+ A(:,3)-PRR;
    
    %将sign的数值与零点做减法得到正负值
    %再将得到的具有正负性的值与每mV的整数值相除,即得到电压多少mV
    M( : , 1)= (M( : , 1)- zerovalue(1))/gain(1);
    M( : , 2)= (M( : , 2)- zerovalue(2))/gain(2);
    %将我们设定的采样个数除以频率即得到这段样品的测定时间。
    TIME =(0:(SAMPLES2READ-1))/sfreq;
    %释放变量
    clear A M_R_H M_L_H PRR PRL;
    数据矩阵M

    矩阵M里就存储了两个导联的信号了,可以单独提取处理。

    3. 注释文件(.atr)

    注释文件里有专家标注的R波位置以及每个心拍的类型,为后续分类提供了可靠的依据。

    100.atr十六进制显示(片段)
    这个存储格式不想过多说明了,可以看看参考文献,里面有详细说明。举个例子说明它的注释信息吧。
    记录100的注释信息

    图中N表示正常心拍,A表示房性心博。

    通过matlab提取注释信息:

    PATH= 'C:UserscccDesktop\数据1_源数据mit-bih-arrhythmia-database-1.0.0';  %数据文件所在文件夹地址
    ATRFILE='100.atr';  %选择记录编号
    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存储了该记录中各心拍的人工标注类型
    ANNOT(length(ANNOT))=[];       % last line = EOF (=0)
    %ATRTIME文件存储了各心拍的人工标注位置
    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);

    1>ANNOT:存储了该记录中各心拍的人工标注类型

    ANNOT文件中的数字,分别代表了当时人工标注的心脏的情况它提供给了我们各心拍专家诊断的结果,用于后续深度学习算法的标签。比如,数字1代表心脏正常搏动,数字2代表左束支传导阻滞,等等,数字所对应的心脏疾病的具体含义可见:

    MIT - bih详细说明和读取代码 - 百度文库

    2>ATRTIME:存储了各心拍的人工标注位置

    ATRTIME文件存储了各心拍的人工标注位置,即它记录了数据中几分几秒出现了一个心拍。而这个矩阵的意义在于后续帮助我们评估心拍定位算法的准确性,或是直接根据它提供的人工标注位置截取心拍。

     

    over,我真棒,撒花~

     

    参考:

    [1]宋喜国,邓亲恺.MIT-BIH心率失常数据库的识读及应用[J].中国医学物理学杂志,2004(04):230-232.

    MIT-BIH数据库数据解析的方法以及使用rdann获取人工标注注释的方法_Candlelight_yujia的博客-CSDN博客_rdann

  • 相关阅读:
    LiteFlow 按照规则配置进行复杂流转
    ImageCombiner 服务端合图
    forest HTTP调用API框架
    smart-doc API文档生成工具
    YAML语法和用法
    拓展mybatisPlus 支持批量插入
    ModbusRTU控制SV660P说明
    .NET RulesEngine(规则引擎)
    Win10自动更新有效强制永久关闭
    Redis 到底是怎么实现“附近的人”这个功能的?
  • 原文地址:https://www.cnblogs.com/hjj-fighting/p/14777826.html
Copyright © 2011-2022 走看看