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
|
|