分享

MIT-BIHECG信号的数据读取方法和Matlab程序

 leelyq 2010-04-23
MIT-BIH ECG 信号的数据读取方法和Matlab程序 收藏
 
 
最近在写一篇基于小波变换的ECG信号压缩算法的论文,遇到了怎样获取ECG信号测试数据的问题,在百度和专业论坛里搜索了一番,发现也有很多朋友为此发愁。现在论文写好了,投稿中,顺便也把怎样获取和处理ECG信号数据的方法写出来,供有需要的朋友参考,省却在百度和论坛里苦苦求索的麻烦,呵呵 ^_^
一、首先,如果是对ECG心电信号进行观察、分析和诊断使用的话,有两个方法:
(1)    从MIT-BIH数据库下载
请参考我前些天发布的文章《MIT-BIH ECG 心电数据的下载和读取图解》,里面有详尽介绍。
(2)    用专门的Matlab心电数据读取程序
我10日在浩惠电子论坛(http://www./bbs/)的“医疗器械”版块找到了读取ECG心电数据的Matlab程序(rddata.m),如获至宝啊!这个程序是由外国人写的,能够读取MIT-BIH数据库 .atr、.dat、.hea三种文件的数据,根据这些数据计算出实际的心电信号值,并绘制出信号波形。程序不大,注释也算齐全,不过是英文的,需要这个程序的朋友请按以下链接下载。
匿名提取文件连接 http://pickup./3497080791233097 
         或登录Mofile,使用提取码 3497080791233097 提取文件
PS: 关于rddata.m的下载,在打开http://pickup./3497080791233097 后,下载链接是在“文件标签”和“文件介绍”之后的地方,夹在两块广告图片之间,共有3个链接:“推荐快车(flashget)高速下载文件 下载文件(IE浏览器) 下载文件(非IE浏览器)”,非常隐蔽,一般点击中间的那个链接“下载文件(IE浏览器)”就会弹出保存对话框了。

二、如果是要对ECG信号进行压缩、编码等信号处理操作
上面程序获得的数据就不便于使用了,因为那是转换为具有实际意义的心电数据,信号数据值一般在-2~2之间,单位是mV。那么,要找新的ECG读取程序来获取数据吗?不用!实际上,程序rddata.m中本身就是把MIT .dat 文件中存储的二值数据转换为十进制数据,然后再进一步处理转换成具有实际意义的心电信号值。我们进行信号处理时,需要用到的就是从二值数据转换来的初始十进制数据,由于 .dat文件中是三个字节存储2个数,即每个数12bits,转换后得到的十进制数范围应该是0~2048。我所理解的数据存储方式图示如下,不知是否正确,仅供参考:
 
由于rddata.m程序中的注释是英文的,且有些地方也说明不清楚,我从程序中截取出将二值数据转换为十进制数据的部分代码,将注释转换为中文,并根据自己的理解作一些补充说明,希望对大家有所帮助!
具体的程序代码如下:
%-------------------------------------------------------------------------
% 程序Fun_ReadECGData 用于读取ECG信号数据,将原始的二值数据转换为十进制数
% 输入参数及其示例:
% PATH= 'D:\MATLAB\R2007b\work\ECG Data'; % 指定数据的储存路径
% HEADERFILE= '117.hea';      % .hea 格式,头文件,可用记事本打开
% DATAFILE='117.dat';         % .dat 格式,ECG 数据
% SAMPLES2READ=2048;          % 指定需要读入的样本数
%                             % 若.dat文件中存储有两个通道的信号:
%                             % 则读入 2*SAMPLES2READ 个数据
% 输出参数:M —— 一个SAMPLES2READ行2列的数据矩阵,每列数据代表一个通道的信号值
%-------------------------------------------------------------------------
                           
function M = Fun_ReadECGData(PATH,HEADERFILE,DATAFILE,SAMPLES2READ)
%------ LOAD HEADER DATA --------------------------------------------------
%------ 读入头文件数据 -----------------------------------------------------
%
% 示例:用记事本打开的117.hea 文件的数据
%
%      117 2 360 650000
%      117.dat 212 200 11 1024 839 31170 0 MLII
%      117.dat 212 200 11 1024 930 28083 0 V2
%      # 69 M 950 654 x2
%      # None
%
%-------------------------------------------------------------------------

%-------------------------------------------------------------------------
% 【注】函数 fprintf 的功能将格式化的数据写入到指定文件中。
% 表达式:count = fprintf(fid,format,A,...)
% 在字符串'format'的控制下,将矩阵A的实数数据进行格式化,并写入到文件对象fid中。该函数返回所写入数据的字节数 count。
% fid 是通过函数 fopen 获得的整型文件标识符。fid=1,表示标准输出(即输出到屏幕显示);fid=2,表示标准偏差。
%-------------------------------------------------------------------------
fprintf(1,'\\n$> WORKING ON %s ...\n', HEADERFILE);   % 在Matlab命令行窗口提示当前工作状态
signalh= fullfile(PATH, HEADERFILE);                           % 通过函数 fullfile 获得头文件的完整路径
fid1=fopen(signalh,'r');                            % 打开头文件,其标识符为 fid1 ,属性为'r'--“只读”
z= fgetl(fid1);                                        % 读取头文件的第一行数据,字符串格式
A= sscanf(z, '%*s %d %d %d',[1,3]);      % 按照格式 '%*s %d %d %d' 转换数据并存入矩阵 A 中
nosig= A(1);                                         % 信号通道数目
sfreq=A(2);                                           % 数据采样频率
clear A;                                                % 清空矩阵 A ,准备获取下一行数据
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;
%------ LOAD BINARY DATA --------------------------------------------------
%------ 读取 ECG 信号二值数据 ----------------------------------------------
%
% 说明:.dat 文件的数据格式
%
%      用 uint8 格式读入 N 个样本,存入矩阵 A 中,则 A 有 N 行、3列,每列一个字节,
%      即每行用三个字节表示两个数m1、m2,每个数 12 bits,故又称为 212 格式
%      m1的低8位存放在 A(:,1),m2的低8位存放在A(:,3),
%      m1的高4位存放在A(:,2)的低4位,m2的高4位存放在A(:,2)的高4位
%     
% 根据上述数据格式,可以用一系列移位、位与操作,提取出十进制格式的双通道信号数据
%
%-------------------------------------------------------------------------
if dformat~= [212,212], error('this script does not apply binary formats different to 212.'); end;
signald= fullfile(PATH, DATAFILE);                    % 读入 212 格式的 ECG 信号数据
fid2=fopen(signald,'r');
A= fread(fid2, [3, SAMPLES2READ], 'uint8')';      % 矩阵A共有SAMPLES2READ行、3列,每列数据都是以uint8格式读入,注意这时数据通过uint8的读入方式已经成为十进制数了
fclose(fid2);
M2H= bitshift(A(:,2), -4);                          % 字节向右移四位,即取字节的高四位,属于信号2的高4位
M1H= bitand(A(:,2), 15);                          % 取字节的低四位,属于信号1的高4位
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;       % 将M1H、M2H分别左移8位,即乘以2^8,再分别加上A(:,1),A(:,2),
M( : , 2)= bitshift(M2H,8)+ A(:,3)-PRR;      % 由于左移时把符号位也移动了,要减去符号位的值
M=M';            % 为了方便后期的数据处理,将输出矩阵 M 转置为2行SAMPLES2READ列
 
 
 

发表于 @ 2008年01月12日 23:55:00 | 评论( 50 ) | 编辑| 举报| 收藏
旧一篇:推荐一款免费的桌面搜索软件 VistaGlance 1.2 ,按文件名称建立索引! | 新一篇:推荐一些常用的中外学术文献数据库网站
查看最新精华文章 请访问博客首页相关文章 opal 发表于2008年1月16日 12:44:21  IP:举报回复删除
请问一下,我做心电信号的聚类分析,如果用心电信号的时间序列,是不是直接用M向量就可以了呢?chenyusiyuan 发表于2008年1月16日 13:01:45  IP:举报回复删除
你好,我认为用于心电信号的聚类分析可以直接使用 rddata.m 文件得出的 M 向量,因为具有实际意义的ECG数据值相对比较小,便于聚类分析。ygy 发表于2008年3月8日 14:22:15  IP:举报回复删除
楼主好,
为什么我使用时候matlab 中没有fget1函数?
Error using ==> fgetl
Invalid file identifier.
我是6.5的,是不是必须在7.0上才可以用?谢谢ygy 发表于2008年3月8日 14:37:08  IP:举报回复删除
晕,我自己忘记设路径了,已解决sunhuinan  发表于2008年3月13日 9:01:52  IP:222.171.23.*举报回复删除
为什么我使用时候matlab 中没有fget1函数?出现下面错误
Error using ==> fgetl
Invalid file identifier.
ygy 你好,你是怎么解决的,多谢了
sunhuinan  发表于2008年3月13日 9:06:47  IP:222.171.23.*举报回复删除
路径我也设了,可是还不对,请各位朋友给我指点。多谢了。sunhuinan  发表于2008年3月13日 9:35:54  IP:222.171.23.*举报回复删除
刚才的问题我已经解决了,不过又出现了下面的问题,在 读取每个通道信号的数据信息出现:
Index exceeds matrix dimensions.
这个问题怎么决绝呀,多谢各位朋友。chenyusiyuan 发表于2008年3月13日 10:46:07  IP:222.200.105.*举报回复删除
sunhuinan,你好,把 Matlab 给出的具体错误信息粘帖出来大家分析一下吧?另外你的Matlab版本是多少?chenyusiyuan 发表于2008年3月13日 10:47:37  IP:222.200.105.*举报回复删除
主要是看Index exceeds matrix dimensions.是哪个变量的数据读取超限了。sunhuinan 发表于2008年3月13日 15:38:15  IP:222.171.23.*举报回复删除
楼主你好,很高兴看见你给我留言了。我要研究的是受干扰的心电信号。它来自于MIT BIH/Noise Stress Test数据库。我下载了118e00.dat,118e00.atr和118e00.hea
我按着你说的编程如下:
>> clear all;
>> PATH= 'C:\Program Files\MATLAB71\work\ECG Noise data';
>> HEADERFILE= '118e00.hea';
ATRFILE= '118e00.atr';
DATAFILE='118e00.dat';
>> SAMPLES2READ=3000;
>> fprintf(1,'\\n{6}gt; WORKING ON %s ...\n', HEADERFILE);
\n{6}gt; WORKING ON 118e00.hea ...
>> signalh= fullfile(PATH, HEADERFILE);
>> fid1=fopen(signalh,'r');
>> z= fgetl(fid1);
>> A= sscanf(z, '%*s %d %d %d',[1,3]);
>> nosig= A(1);
>> sfreq=A(2);
>> clear A;
>> for k=1:nosig
z= fgetl(fid1);
A= sscanf(z, '%*s %d %d %d %d %d',[1,9]);
dformat(k)= A(1);
gain(k)= A(2);
bitres(k)= A(3);
zerovalue(k)= A(4);
firstvalue(k)= A(5);
end;
Index exceeds matrix dimensions.
希望楼主帮我看看,我很着急呀,我没学过matlab,现在刚开始学一点,所以有些看不懂呀。
sunhuinan 发表于2008年3月13日 15:39:55  IP:222.171.23.*举报回复删除
对了,我的matlab的版本是7.1的chenyusiyuan 发表于2008年3月13日 15:50:48  IP:222.200.105.*举报回复删除
应该是这里出错了:
A= sscanf(z, '%*s %d %d %d %d %d',[1,9]);
数字‘9’应改为‘5’ !sunhuinan 发表于2008年3月13日 15:53:24  IP:222.171.23.*举报回复删除
>> clear all;
>> PATH= 'C:\Program Files\MATLAB71\work\ECG Noise data';
>> HEADERFILE= '118e00.hea';
>> ATRFILE= '118e00.atr';
>> DATAFILE='118e00.dat';
>> SAMPLES2READ=3000;
>> fprintf(1,'\\n{6}gt; WORKING ON %s ...\n', HEADERFILE);
\n{6}gt; WORKING ON 118e00.hea ...
>> signalh= fullfile(PATH, HEADERFILE);
>> fid1=fopen(signalh,'r');
>> z= fgetl(fid1);
>> A= sscanf(z, '%*s %d %d %d',[1,3]);
>> nosig= A(1);
>> sfreq=A(2);
>> clear A;
>> for k=1:nosig
z= fgetl(fid1);
A= sscanf(z, '%*s %d %d %d %d %d',[1,5]);
dformat(k)= A(1);
gain(k)= A(2);
bitres(k)= A(3);
zerovalue(k)= A(4);
firstvalue(k)= A(5);
end;
Index exceeds matrix dimensions.
这个是我编的程序,总是出现这个错误呀。chenyusiyuan 发表于2008年3月13日 15:54:46  IP:222.200.105.*举报回复删除
[1,5]分别对应于'%*s %d %d %d %d %d',具体原因可查看Matlab的帮助文件有关‘sscanf’的说明。
我的Email是 chenyusiyuan@126.com,可以发邮件方便讨论。也可以点击页面上方的“联系作者”通过csdn的邮件系统和我交流 ^_^孙会楠 发表于2008年3月13日 16:02:07  IP:222.171.23.*举报回复删除
我该为[1,5]了,可是还是不对su 发表于2008年3月22日 23:22:05  IP:举报回复删除
请问你会编写The Creighton University Ventricular Tachyarrhythmia Database这个里面的数据吗,我急需要谢谢请发邮件给我sulan00@163.comnkj 发表于2008年3月25日 15:35:27  IP:举报回复删除
为什么我的matlab 中也没有fget1函数?出现下面错误
Error using ==> fgetl
Invalid file identifier.
ygy sunhuinan两位楼主你们好,你们是怎么解决的,多谢了
chenyusiyuan 发表于2008年3月25日 16:05:26  IP:222.200.105.*举报回复删除
nkj,你好,可能你还没设置好路径吧,要先在命令行设置好下面几个参数:
% PATH= 'D:\MATLAB\R2007b\work\ECG Data'; % 指定数据的储存路径
% HEADERFILE= '117.hea'; % .hea 格式,头文件,可用记事本打开
% DATAFILE='117.dat'; % .dat 格式,ECG 数据
% SAMPLES2READ=2048; % 指定需要读入的样本数nkj 发表于2008年3月26日 16:46:43  IP:218.2.216.*举报回复删除
版主你好,我都设置好了,还是不行!chenyusiyuan 发表于2008年3月26日 18:46:44  IP:222.200.105.*举报回复删除
有关下面这个错误:
Error using ==> fgetl
Invalid file identifier.
我觉得问题还是在路径的设置上,函数 fgetl() 的代码中有关 Invalid file identifier 的错误是这样定义的:
if isempty(fopen(fid))
error ('MATLAB:fgetl:InvalidFID','Invalid file identifier.')
end
也就是说,如果 fopen 无法打开指定的文件,fopen(fid)则为空,从而出现 Invalid file identifier 的错误提示。所以要再仔细检查一下路径。nkj 发表于2008年3月27日 16:16:04  IP:举报回复删除
果然是!我的问题已解决!
非常感谢!zhangw 发表于2008年3月28日 16:06:34  IP:219.239.227.*举报回复删除
你们好,liu 发表于2008年5月2日 16:11:34  IP:举报回复删除
版主你好,请问通过上面的程序把心电图数据读入后它保存在哪里啊?是矩阵形式的吗?读进来后对它进行滤波怎么弄啊?liu 发表于2008年5月2日 16:14:06  IP:举报回复删除
还有,如果我要读取一个通道的心电图是不是把里面包含M( : , 2)的语句去掉就好了啊?chenyusiyuan 发表于2008年5月2日 19:46:42  IP:举报回复删除
liu 你好,读入的心电数据存在矩阵M中,M是一个2*L的矩阵,其中L为心电数据的长度;M的每一行存放一个通道的心电数据。liu 发表于2008年5月3日 9:24:53  IP:举报回复删除
谢谢版主了!呵呵liu 发表于2008年5月3日 9:53:58  IP:举报回复删除
好像不对啊,M是一个2*L的矩阵的话,为什么显示程序里这样写呢:plot(TIME, M(:,1),'r'); 这里M(:,1)的话不是代表第一列吗?这样的话M还是一个2*L的矩阵吧?chenyusiyuan 发表于2008年5月3日 20:16:05  IP:举报回复删除
哦,不好意思,我这篇文章最后一行对M转置成2*L,原来的程序里是L行2列的。我的邮箱是chenyusiyuan@126.com,欢迎来信交流。kebi 发表于2008年5月5日 20:45:07  IP:222.200.105.*举报回复删除
师弟,不错,不错!秀 发表于2008年5月16日 21:33:09  IP:举报回复删除
function M = Fun_ReadECGData(PATH,HEADERFILE,DATAFILE,SAMPLES2READ)
|
Error: Function definitions are not permitted at the prompt or in scripts.
请问这个怎么解决啊?mutusanshi  发表于2008年6月4日 14:34:08  IP:202.206.249.*举报回复删除
你好,我按你说得打开http://pickup./3497080791233097 ,然后输入提取码3497080791233097,怎么不能下载 rddata.m,谢谢帮忙!chenyusiyuan 发表于2008年6月4日 16:47:27  IP:222.200.105.*举报回复删除
关于rddata.m的下载,在打开http://pickup./3497080791233097 后,下载链接是在“文件标签”和“文件介绍”之后的地方,夹在两块广告图片之间,共有3个链接:“推荐快车(flashget)高速下载文件 下载文件(IE浏览器) 下载文件(非IE浏览器)”,非常隐蔽,一般点击中间的那个链接“下载文件(IE浏览器)”就会弹出保存对话框了。mutusanshi  发表于2008年6月17日 21:15:01  IP:202.206.249.*举报回复删除
楼主,非常感谢你,请问下rddata.m程序怎么使用才能把心电数据读取并在matlab中显示出心电波形,我刚接触,谢谢你!给我详细说下过程!mutusanshi  发表于2008年6月17日 21:24:13  IP:202.206.249.*举报回复删除
楼主,非常感谢你,请问下rddata.m程序怎么使用才能把心电数据读取并在matlab中显示出心电波形,我刚接触,谢谢你!给我详细说下过程!lylpf0122 发表于2008年9月7日 22:18:17  IP:举报回复删除
为什么程序执行到这一句
if M(1,:) ~= firstvalue, error('inconsistency in the first bit values'); end;
出现这样的错误提示
inconsistency in the first bit values
这是什么错误啊???reachecg 发表于2008年10月13日 12:03:05  IP:举报回复删除
真强,真的感谢!!!xrhcf 发表于2008年12月21日 10:35:18  IP:举报回复删除
请问,图形里面的两条线分别是什么意思呀xrhcf 发表于2008年12月21日 10:36:26  IP:举报回复删除
我看不懂那个程序
但是,我想如果建立分类器的话,用哪条线才对呀xrhcf 发表于2008年12月21日 10:36:49  IP:举报回复删除
麻烦给解释一下,不胜感激xrhcf 发表于2008年12月21日 11:02:29  IP:举报回复删除
我的邮箱:xrhcf@163.com,麻烦给我解释一下哈,谢谢。。。。。huinan2009 发表于2009年2月22日 14:42:47  IP:举报回复删除
心电信号有负值吗
从数据库中读取的值是-2~+2
而用上面的程序读出来的怎么不在这个范围呀chenyusiyuan 发表于2009年2月24日 20:35:58  IP:举报回复删除
回复 huinan2009:你好,文中的程序只是实现了部分功能,完整的程序代码请下载‘rddata.m’,文中已给出下载链接
sdcxwlz6 发表于2009年2月24日 21:50:13  IP:举报回复删除
请问楼主 图形里面的两条线分别是什么意思呀?是两个通道的信号么,要是的话有什么区别么?
谢谢 谢谢chenyusiyuan 发表于2009年2月24日 23:46:09  IP:举报回复删除
回复 sdcxwlz6:应该是双通道信号,具体每条信号代表什么我不清楚,我不是做心电处理。只是学习小波信号压缩时用心电信号作为信号源而已。不好意思啊
lantian1124 发表于2009年3月17日 10:00:28  IP:举报回复删除
真不好意思,问个比较傻的问题哈,如果我想使用rddata.m读取的信号,并对它进行处理应该怎么用那,直接下载load rddata.m吗lidss1234 发表于2010年1月28日 10:37:55  IP:举报回复删除
在心电自动分析中,对QRS波群分类,在自动分析中用DeMix方法如何实现。各位老大,请教一下。匿名用户 发表于2010年3月9日 20:16:30  IP:举报回复删除
非常谢谢你的程序 我已经能能够取得很大的进步micheal910 发表于2010年3月28日 18:36:04  IP:举报回复删除
LZ请问 用那个程序 怎么读MIT-BIH数据啊 具体步骤 谢谢还有那个程序到MATlab2008b中为何出现 ??? Error using ==> fgetl at 44 Invalid file identifier. Use fopen to generate a valid file identifier.的错误 能解释下吗 谢谢zst610 发表于2010年4月10日 12:18:35  IP:举报回复删除
请问楼主有没有关于用MATLAB读取USB传送的心电数据的程序?本人刚开始做这方面的东西,想学习学习···chenyusiyuan 发表于2010年4月11日 23:29:13  IP:举报回复删除
回复 zst610:不好意思啊,专业所限,对心电数据读取和处理了解并不多,仅限于相关的2篇博文,请见谅。不过具体编程细节问题欢迎来信讨论,谢谢。
shinobifc 发表于2010年4月15日 16:01:43  IP:举报回复删除
你好,我刚刚做ECG方面的东西,对你的解释有两点疑问:1.在LOAD BINARY DATA中,A是以uint8形式读取的,所以我感觉PRL和PRR的设置没有必要(当然,可以用于检验,健壮程序),因为他们的值都是0;2.既然读取的是8位,又何来M( : , 1),M( : , 2)中移动8位的操作呢?我的认为是有个盒子,就8个格,有效的数据在后四个格,你一下挪8位,岂不是把4位有效数据都移出去了?还是我理解错了,A是8位的,PRL、PRR、M等并没有8位的限制?刚刚接触,希望解惑!匿名用户 发表于2010年4月19日 17:33:58  IP:举报回复删除
请问楼主RR-interval可用rddata.m 来实现吗?发表评论
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/chenyusiyuan/archive/2008/01/12/2040234.aspx

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多