最近在寫一篇基於小波變換的ECG信號壓縮算法的論文,遇到了怎樣獲取ECG信號測試數據的問題,在百度和專業論壇里搜索了一番,發現也有很多朋友為此發愁。現在論文寫好了,投稿中,順便也把怎樣獲取和處理ECG信號數據的方法寫出來,供有需要的朋友參考,省卻在百度和論壇里苦苦求索的麻煩,呵呵 ^_^
一、首先,如果是對ECG心電信號進行觀察、分析和診斷使用的話,有兩個方法:
(1) 從MIT-BIH數據庫下載
請參考我前些天發布的文章《MIT-BIH ECG 心電數據的下載和讀取圖解》,里面有詳盡介紹。
http://blog.csdn.net/chenyusiyuan/archive/2008/01/06/2027887.aspx
(2) 用專門的Matlab心電數據讀取程序
我10日在浩惠電子論壇(http://www.hheet.com/bbs/)的“醫療器械”版塊找到了讀取ECG心電數據的Matlab程序(rddata.m),如獲至寶啊!這個程序是由外國人寫的,能夠讀取MIT-BIH數據庫 .atr、.dat、.hea三種文件的數據,根據這些數據計算出實際的心電信號值,並繪制出信號波形。程序不大,注釋也算齊全,不過是英文的,需要這個程序的朋友請按以下鏈接下載。
http://download.csdn.net/source/3383369
二、如果是要對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列