基于MATLAB的脉搏信号处理软件系统Word下载.docx
《基于MATLAB的脉搏信号处理软件系统Word下载.docx》由会员分享,可在线阅读,更多相关《基于MATLAB的脉搏信号处理软件系统Word下载.docx(32页珍藏版)》请在冰豆网上搜索。
![基于MATLAB的脉搏信号处理软件系统Word下载.docx](https://file1.bdocx.com/fileroot1/2022-12/1/d399f8eb-7334-4346-8d1e-256c3379972d/d399f8eb-7334-4346-8d1e-256c3379972d1.gif)
除了经典的一些算法外,MATLAB还提供了丰富的数据分析和处理功能模块,如神经网络、小波分析、信号处理、图像处理、自动控制、模糊控制、系统仿真等,因此MATLAB是一种高效的编程软件。
本文介绍利用MATLAB软件作为技术平台,实现对统脉搏波快速、准确实时显示,而且实现方法简单有效,有一定的实用性。
2软件总体界面与总体设计思路
图2.1未运行前密码登陆界面
图2.2运行后输入错误的密码登陆界面
图2.3运行后输入正确的密码登陆界面
2.2脉搏信号处理系统界面
图2.4未运行前的脉搏信号处理系统界面
图2.6运行后的脉率曲线回放与判断脉率正常、输出脉搏信息
2.3软件总体设计思路
3信号回放模块设计
3.1脉搏波信号滤波
脉搏信号是强干扰下的微弱信号,脉搏信号幅度很小,大约是微伏到毫伏的
数量级范围,其主要频带范围在0~20Hz之间。
一般情况下为1Hz左右,脉搏信号可看成一个准直流信号,也可看成是一个甚低频交变信号。
根据脉搏功率谱能量分析,健康人脉搏能量绝大多数分布于0.5~5Hz,而病人脉搏在1Hz以下和较高频段(如5Hz以上或10Hz以上)仍有相当一部分的能量分布。
脉搏信号极容易引入干扰,一般情况下,由体表检测到的脉搏波主要有三种干扰:
基线漂移,高频随机干扰和运动伪差噪声,还有一些干扰,比方工频干扰,等,这些干扰较之前三种干扰比较小,而且很容易去掉]。
1).基线漂移:
这种噪声是由于被测对象的呼吸运动和身体移位而产生的,呼吸的频率分量通常在0.8Hz以下,每个人的呼吸频率也不同;
身体移位也可以用低频分量来表征,因此基线漂移基本上都是趋势分量和低频分量。
2).高频随机干扰:
脉搏信号的采集过程中有好多随机噪声和环境干扰的影响,这些噪声都表现为高频噪声,在5Hz以上。
3).运动伪差噪声:
由于对病人进行血氧检测时,病人手指(或脚趾)经常会发生
运动,使手指(或脚趾)与传感器之间的距离发生位移,从而得到导致测量的病人脉
搏波形很不稳定的一种噪声,这种噪声和信号在同一个频带范围内,是脉搏信号
去噪的一个重点和难点。
所以,为了对信号做准确的分析,在分析处理之前必须做一些必要的预处理。
针对信号中存在噪声的特点,基线漂移和呼吸等低频干扰在1Hz以下,而脉搏信号主要在低频范围,所以可以设计让信号先通过一个巴特沃斯带通滤波器,借以滤除基线漂移、呼吸引起的干扰〔考虑到不丧失太多的其他信息,通带截止频率设置为Wp=[0.9,50],阻带截止频率设置为Ws=[0.3,140],通带波纹系数Rp=3,阻带波纹系数Rs=10〕,如图3.2,然后再通过一个切比雪夫二型滤波器滤除固定的工频干扰〔通带截止频率设置为Wp=[30,65],阻带截止频率Ws=[45,55],通带波纹系数Rp=3,阻带波纹系数Rs=60〕,如图3.3。
由于Butterworth滤波器通带内有最大的平滑特性,信号经过后衰减小,因此我们选用Butterworth带通滤波器滤除基线漂移和呼吸等引起的干扰,但由于IIR滤波器本身固有的缺点,信号通过Butterworth带通滤波器后相位会失真,故我们可设计零相位Butterworth带通滤波器去噪。
50Hz固定工频在频域中是一个点,因而要求设计的带阻滤波器有好的截止特性,而切比雪夫II型滤波器有较好的截止特性,并且在其通带内单调,故而设计零相位切比雪夫II型滤波器滤除工频干扰。
流程图如下:
图3.1脉搏信号滤波流程图
图3.2巴特沃斯带通滤波器图3.3带阻切比雪夫II型滤波器
3.2脉搏信号回放按钮设计思路
信号回放模块设计如图3.4,考虑到用户使用的方便性,信号回放过程中才可对信号进行放大与缩小操作,或者快进退操作,在回放过程中,退出系统按钮处于不激活状态,关闭窗口和继续回放也处于不激活状态,只有当信号暂停时,才使前面三个按钮激活,或者进行下一步,输出脉率曲线功能。
图3.4信号回放模块设计
1).信号回放:
主要采用了Matlab中的while、if、plot、axis、global、set、pause命令。
思路先是将信号和滤波信号用plot命令分别在axes1、和axes2上画出图形,接着用axis移动坐标轴,用while进行死循环,让信号不停的回放。
2).信号暂停:
主要利用if-break语句来实现,在信号回放的控件Callback函数中,定义一个全局变量flg1,初始flg1=1,接着在while每次循环中,检测flg1的值,为1继续循环回放,为0的话跳出循环,停止回放。
所以,要信号暂停回放,只需要在信号暂停按钮的Callback函数中,定义一个全局变量flg1,并命flg1=0即可。
3).继续回放:
也是利用全局变量来实现,当信号暂停回放时,记录下些时的X轴和Y轴的长度大小,点击继续回放就还是用plot命令分别在axes1、和axes2上画出图形,接着用axis移动坐标轴,用while进行死循环,让信号不停的回放。
只不过这里要注意的是,此时坐标轴的移动不是从0开始,而是从暂停时的记录下来的全局变量X轴的长度大小xmin、xmax。
4).关闭窗口:
直接用delete(allchild(handles.axes1));
2));
语句
4信号放大与缩小模块设计
4.1设计界面
考虑到信号回放过程中每个人的脉搏的曲线都会有所不一样,两个波峰之间的时间,波峰的数值大小,为了能方便看到每个点的数据,我在信号放大与缩小模块中加了四个按钮,可沿X轴缩小放大和沿Y轴缩小放大,如图4.1。
另外,考虑到操作的方便性,设计了在信号回放或者继续回放的过程中,这四个按钮才被激活,信号暂停时,这四个按钮都处于不激活的状态。
图4.1信号放大与缩小模块
4.2信号放大与缩小按钮设计思路
1).X轴缩小:
即将信号沿X轴压缩,如图4.3,X轴的长度变长,但是Y轴保持不变,这里,主要也是利用axis命令,实时的改变X轴长度,并且用while进行死循环,直到遇到flg1=0,才跳出循环。
程序流程图如下:
图4.2信号放大流程图
图4.3X轴缩小
2).X轴放大:
即将信号沿X轴拉伸,如图4.4,X轴的长度变短,但是Y轴保持不变,这里,主要也是利用axis命令,实时的改变X轴长度,并且用while进行死循环,直到遇到flg1=0,才跳出循环。
图4.4X轴放大
3).Y轴缩小:
即将信号沿Y轴压缩,如图4.5,Y轴的长度变长,但是Y轴保持不变,这里,主要也是利用axis命令,实时的改变X轴长度,并且用while进行死循环,直到遇到flg1=0,才跳出循环。
4).Y轴放大:
即将信号沿Y轴拉伸,如图4.6,Y轴的长度变短,但是Y轴保持不变,这里,主要也是利用axis命令,实时的改变X轴长度,并且用while进行死循环,直到遇到flg1=0,才跳出循环。
图4.6Y轴放大
5信号快进退模块设计
5.1设计界面
考虑到有时信号的采样时间很长,为了能快速浏览信号的波形或者看之前的波形,我特别又设计此模块。
图5.1信号快进退模块界面
1).快进:
设计全局变量pauset=pauset*0.5,即让每次移动坐标轴的时间间隔减小,再令Xmin=Xmin+0.1,Xmax=Xmax+0.1,移动X轴,这样回放的速度就会变快,按钮每按一次,回放速度加快一倍。
2).慢进:
设计全局变量pauset=pauset*2,即让每次移动坐标轴的时间间隔加大,再令Xmin=Xmin+0.1,Xmax=Xmax+0.1,移动X轴,这样回放的速度就会变慢,按钮每按一次,回放速度减少一倍。
3).快退:
设计全局变量pauset=pauset*0.5,即让每次移动坐标轴的时间间隔减小,再令Xmin=Xmin-0.1,Xmax=Xmax-0.1,移动X轴,这样回放的速度就会变快,按钮每按一次,回放速度加快一倍。
4).慢退:
设计全局变量pauset=pauset*2,即让每次移动坐标轴的时间间隔减小,再令Xmin=Xmin-0.1,Xmax=Xmax-0.1,移动X轴,这样回放的速度就会变快,按钮每按一次,回放速度加快一倍。
6脉率实时处理模块设计
6.1脉搏信号峰值提取
脉搏信号的特征提取是脉搏信号分析中的关键,能不能准确的提取出来脉搏信号的特征关系到能不能准确的分析脉搏信号,其时域中提取的主要特征有脉搏的峰值、周期等。
而在这其中最重要的是峰值的提取,准确的提取出来峰值,可为进一步分析其周期,脉率等其他参数打下基础,如图6.1显示的脉搏波,h为脉搏波形的高度。
图6.1脉搏波形的高度
提取信号的峰值基本思想是基于阈值的方法,统计分析采集到得脉搏信号发现,虽然每个脉搏波的波峰值大小并不相同,但他们总在一个范围内波动,波动的范围基本上不超过最大波形高度的0.3倍,为了更为可靠的检测波峰,以0.4倍为参考。
因此可以认为波峰点是在每个脉搏周期中波形的最大值附近,大于其邻域内所有点的点。
由于所用数据采样频率为800HZ,通过对大量脉搏波测量数据分析,把邻域长度定义为400个数据点可以准确识别波峰点。
假设采集到的脉搏波为数字信号序列
实际波峰
的判别条件为:
公式中
,
为波峰点的位置。
提取出波峰点的位置后,其他时域的特征,如周期、脉率等可相应而出。
峰值提取程序流程如下:
图6.1判断脉搏峰值程序流程图
6.2脉率实时处理界面设计
界面设计如图6.2,脉率信号输出窗口可输出平均脉率、采样频率、采样时长、最大脉率、最小脉率等。
图6.2脉率实时处理模块
6.3脉率实时处理按钮设计思路
1).输出脉率曲线:
实时动态输出脉率变化趋势曲线与脉率峰值变化曲线,如图6.3同时在文本框1中实时平均脉率,这也是实时更新输出。
图6.3软件实时输出脉率趋势曲线
2).暂停回放:
停止脉率曲线的更新和平均脉率的更新,同时激活输出脉搏信息按钮
3).输出脉搏信息:
输出所有脉率点的平均脉率,同时在列表中输出采样频率、采样时长、最大脉率、最小脉率,并跳出判断脉率是否正常的信息框〔如图6.4〕。
之后激活频谱分析按钮。
图6.4输出脉搏信号
图6.5输出脉搏信息到列表和文本框
图6.6判断脉率是否正常
4).频谱分析:
输出滤波后信号的幅频图和信号功率谱图
图6.7频谱分析
5).清除波形:
清除窗口的绘图
6).输出文档:
输出TXT文档,以电脑当前的日期和时间命名,包含有所有计算出的脉率点,以及采样频率、采样时长、最大脉率、最小脉率。
7参考文献
[1]罗志昌,张松,杨益民,脉搏波的工程分析与临床应用[M].北京:
科学出版社,2006:
1-20
[2]郑阿奇,MATLAB实用教程[M].北京:
电子工业出版社,2004.
[3]王炳和,罗建,相敬林等.人体脉搏功率谱分析与中医脉诊机理研究[J].西北大学学报,2001,31
(1):
21-25.
8致谢
这里,首先要感谢候文生老师提供让我设计此软件的时机。
软件完成后,感触颇多,觉得又学到了点了知识,很有成就感。
软件前前后后花了总共一个礼拜的时间,这星期里起床后吃饭到睡觉时都在想着怎么来编写代码,怎么来完善软件功能,一整天开机就Matlab,脑子就直想着怎么写程序。
设计每个控件按钮时,总会碰到很多问题,因为调试时各种Bug,光是界面就重画了10来次。
但我不放弃不后退,每次通过网上搜集资料、反复查看代码、和同学之间进行交流总能把问题解决好,而且又想到新的功能设计。
虽说软件还不是很强大,设计也还不是很好,但还是算是自己设计的第一个软件。
最后,衷心感谢候老师安排的此次实验,希望以后还能有更多这样的实践时机。
附录:
〔程序太多了,只附上主要部分的程序〕
1.打开数据
functionpushbutton5_Callback(hObject,eventdata,handles)
kong='
'
;
set(handles.listbox1,'
string'
kong);
set(handles.edit1,'
axes(handles.axes1);
gridon;
axis([0,1,-2,4])
axes(handles.axes2);
globalstr;
[filename,pathname]=...
uigetfile({'
*.txt'
},'
choose'
);
str=[pathnamefilename];
set(handles.pushbutton1,'
enable'
'
on'
functionpushbutton6_Callback(hObject,eventdata,handles)
button1=questdlg('
你确定退出吗?
退出程序'
确定'
取消'
ifstrcmp(button1,'
)
close(gcf);
end
functionpushbutton1_Callback(hObject,eventdata,handles)
set(handles.pushbutton2,'
set(handles.pushbutton5,'
off'
set(handles.pushbutton6,'
set(handles.pushbutton10,'
set(handles.pushbutton11,'
set(handles.pushbutton15,'
set(handles.pushbutton16,'
set(handles.pushbutton17,'
set(handles.pushbutton18,'
set(handles.pushbutton19,'
set(handles.pushbutton20,'
set(handles.pushbutton21,'
set(handles.pushbutton22,'
globalstr
globalt
globalmaibo
globalymin
globalymax
globalxmin
globalxmax
globalpauset
pauset=0.5;
data=load(str);
t=data(:
1);
maibo=data(:
2);
ymin=min(data(:
2))-0.5;
ymax=max(data(:
2))+0.5;
%%
globals21
globaldt
yy=data;
x=yy(:
2)'
dt=yy(:
1)'
fs=800;
%%去除基线漂移
k=.7;
%cut-offvalue
fc=0.3/fs;
alpha=(1-k*cos(2*pi*fc)-sqrt(2*k*(1-cos(2*pi*fc))-k^2*sin(2*pi*fc)^2))/(1-k);
y=zeros(size(x));
fori=1:
size(x,1)
y(1,:
)=filtfilt(1-alpha,[1-alpha],x(1,:
));
end
x1=x-y;
%%butter带通滤波
Wp=[0.950]/400;
Ws=[0.3140]/400;
[n,Wn]=buttord(Wp,Ws,3,10);
[b,a]=butter(n,Wn);
%%cheby去除50hz工频干扰
Wp1=[3065]/400;
Ws1=[4555]/400;
rp=3;
rs=60;
[n1,Wn1]=cheb2ord(Wp1,Ws1,rp,rs);
[b1,a1]=cheby2(n1,rs,Wn1,'
stop'
%%信号之间的比照
x2=filtfilt(b,a,x1);
s21=filtfilt(b1,a1,x2);
axes(handles.axes1);
plot(t,maibo);
title('
原始脉搏信号'
xlabel('
时间/s'
ylabel('
幅值/mv'
grid
set(gca,'
position'
[1027.512020]);
xmin=0;
xmax=max(t)/10;
axis([xmin,xmax,ymin,ymax])
axes(handles.axes2);
plot(dt,s21);
grid;
滤波去噪后脉搏信号'
[10312020]);
%%%
globalflg1
flg1=1;
while1
if(flg1==0)
break;
end
xmin=xmin+0.1;
xmax=xmax+0.1;
axis([xmin,xmax,ymin,ymax]);
%移动坐标系
pause(pauset);
guidata(hObject,handles);
functionpushbutton17_Callback(hObject,eventdata,handles)
xmin=1/2*xmin;
functionpushbutton15_Callback(hObject,eventdata,handles)
pauset=pauset*0.5;
functionpushbutton7_Callback(hObject,eventdata,handles)
set(handles.pushbutton8,'
set(handles.pushbutton9,'
set(handles.pushbut