超⼊门级-基于中值滤波处理ECG信号的基线漂移-Python-MIT-BIH数据集
中值滤波处理⼼电信号的基线漂移
距离上次发东西已经8个⽉,我已经本科毕业成为了⼀名研究⽣,但是我已经暂时弃硬从软,暂时开始做深度学习⽅向了,这篇⽂章就算⼀个我研究⽣学习的第⼀次笔记分享,我也会争取写的⾮常详细,ECG信号的处理是我第⼀个课题中的⼀部分,因为现实中的信号在采集的过程中都会存在噪声和⼲扰,所以如果想⽤ECG(Electrocardiogram)⼼电图中的特征作为深度学习的输⼊,那就要尽可能还原这个信号去除⼲扰之后原本的样⼦,这些⼲扰在专业上⼜被称为噪声,ECG信号有三⼤噪声-基线漂移,⼯频⼲扰,肌电⼲扰,⽽中值滤波就被⽤于处理基线漂移⼲扰,为了得到有效的ECG信号这类噪声是必须消除的
⼀.ECG中的基线漂移介绍
基线漂移通俗的讲就是由于测量电极和⼈体⾃⾝呼吸的原因,会导致测出来的信号会有上下的抖动,这类抖动将难以定位ECG信号的特征点,使测出来的数据可⽤性降低,接下来放两张图⽚
1.原始的⼼电信号
2.去除基线漂移之后的⼼电信号
两会精神解读可以看到第⼀张的原始信号中的⼼电波形"错落有致",这就好像,我们要给⼀个班级的同学测量⾝⾼数据,结果这个班的同学到操场以后有的站在砖头上有的站在⼟坑⾥,⽽我们是以每个同学头顶到地⼼
的距离来表⽰每个⼈的⾝⾼的,就好像以地⼼为原点建⽴了⼀个坐标轴,⽽这个时候由于有⼟坑和砖头的影响,测得的数据不能很好的反应每个同学真实的⾝⾼关系(这块应该不难理解,可以稍微想⼀下)如果以此时的数据作为代表学⽣⾝⾼的依据的话,⽆论是⽤这个数据排队列还是排集体照都不会得到⼀个我们想要的效果,⽽如果我们要测得更具有参考价值的数据,那我们可以采⽤填坑垫砖头的⽅法,让所有的同学都能站到站到⼀个⽔平⾯上,这个时候测得的数据就会变的更具有参考价值,⽽每⼀个⼼电信号就像⼀个同学,填坑垫砖头的过程就是去除基线漂移的过程,去除基线漂移之后如上⾯的第⼆个图,也会让信号看起来’板正’了不少
⼆.中值滤波
yelp什么叫中值滤波,怎么个滤法呢,简单点解释,就是让每⼀个数,被包括他周围在内的数中的中位数代替
对列表⾥的每⼀个元素进⾏中值滤波计算,我们使⽤的是Python中的scipy库的dfilt(滤波数据, 窗⼤⼩)
这⾥有⼀个简单的例⼦
import scipy # 导⼊scipy模块
window_size =3
x=[70,80,30,20,10,90,0,60,40,50]# 定⼀个列表数组
print(dfilt(x,window_size))#⼀维中值滤波
# [70 70 30 20 20 10 60 40 50 40] #打印滤波后的输出值
接下来我们关注对应的输出值是如何实现的
2.1对于中间数据
输⼊为[70, 80, 30, 20, 10, 90, 0, 60, 40, 50]
输出为[70, 70, 30, 20, 20, 10, 60, 40, 50, 40]
我们先⽤数组中的第⼆个数据举例⼦原来为80滤波后为值变为70
⾸先我们关注到dfilt(x,window_size)
这⾥的参数窗的⼤⼩window_size设置为了3在⼀维数据中指的是以对应数为中⼼左右各取(window_size-1)/2个数以这些数作为滤波的基础数据
(window_size-1)/2为了让这个数除尽所以window_size值必须为奇数不然会报错
求这三个数的中位数赋给对应的值bro
我们再把输⼊的数据拿出来
x=[70, 80, 30, 20, 10, 90, 0, 60, 40, 50]
对这三个数据进⾏排序 70,80,30 → 30,70,80
我们再把输出拿出来[70 70 30 20 20 10 60 40 50 40]
对应80这个位置数据变为了70consultants
2.2对应两侧数据
那两侧的数据在原序列中取不到3个数据怎么办呢
例如第⼀个数据70左边没有数据这不就不够3个数了吗
对应这种情况我们运算的时候会在左边偷偷补⼀个0
linpack
0,[70, 80, 30, 20, 10, 90, 0, 60, 40, 50]
算0,70,80这三个数的中位数
所以对应输出[70 70 30 20 20 10 60 40 50 40]这个数还是70
同理最右边的50
[70, 80, 30, 20, 10, 90, 0, 60, 40, 50],0
2011考研英语对这三个数据进⾏排序 40,50,0 → 0,40,50
所以对应输出[70 70 30 20 20 10 60 40 50 40]这个数变成了40
三.ECG信号的读取
好了我们现在知道对于⼀维信号来说中值滤波是什么样⼦的了
⽽我们在进⾏处理时每⼀个⼼电信号其实就是被记录为⼀串数字的数据,每⼀个数据代表的是当前时刻信号的幅值,每两个数据的采样间隔时间为频率的倒数(这⾥要是懵住了可以稍微想⼀下)我们只要把这串数字扔进去,算好每⼀个数滤波后对应的中值所组成的⼀维数组,⽽这个新的⼀维数组的数据整
体表现出来的就是总体的偏移的情况,也就叫做是基线,这块不好理解的话到后⾯有滤波前后的基线对⽐帮助⼤家理解,到这总体什么个思路⼤致了解了,那⼼电信号那初始的⼀维数据哪来呢
这⾥我们⽤的是MIT-BIH数据集,在这个数据库⾥就有我们要分析的⼼电信号数据
MIT-BIH 是由美国⿇省理⼯学院提供的研究⼼律失常的数据库
链接: .
点进去之后下翻点击Download the ZIP file就可以下载MIT-BHI数据集how do you do是什么意思
下载成功之后你将会得到⼀个叫这个名字的压缩⽂件
我们建⽴⼀个⼯程将该⽂件夹解压在⼯程⽬录下
之后我们先来简单读取⼀下⼼电信号打出来个图看看
# 导⼊⼼电信号处理函数库
import wfdb
# 导⼊python的类matlab绘图函数库
rejectingimport matplotlib.pyplot as plt
# 读取本地的100号记录,从0到25000,读取模拟信号,通道0
record = wfdb.rdrecord('mit-bih-arrhythmia-databa-1.0.0/100', sampfrom=0, sampto=25000, physical=True, channels=[0,]) # 读取,从第145个数据到第756个数据
ventricular_signal = record.p_signal[144:756]
# 打印标题
plt.title("ventricular signal")
# 打印信号
plt.plot(ventricular_signal)
# 显⽰图像
plt.show()
wfdb 和 matplotlib 两个库需要⾃⼰在电脑的cmd命令提⽰符操作框内使⽤pip命令安装安装
命令分别如下
pip install wfdb
pip install matplotlib
其中这⾥是读取⼼电信号最关键的⼀句
record = wfdb.rdrecord('mit-bih-arrhythmia-databa-1.0.0/100', sampfrom=0, sampto=25000, physical=Fal, channels=[0,])
解释⼀下这⾥⽤到的各个参数
⾸先第⼀个参数’mit-bih-arrhythmia-databa-1.0.0/100’
这个参数要表达的意思是要读取mit-bih-arrhythmia-databa-1.0.0⽂件夹下的第100号⼼电数据的参数这个⽂件夹的名字我们⽑都没变直接给粘过来了
sampfrom=0, sampto=25000 这两句的意思是提取对应⼼电信号中第0到第25000个样本点
physical=Fal 这⾥设置成Fal 则提取出的信号为d_signal数字信号也就是没有转换成⼼电信号电压
易程科技
幅度之前的原始信号的值可以代表最⼤的精度⽽设置成Ture
则会读取出每⼀个点的模拟信号值也就是对应采样点的mv电压值p_signal
上图对⽐⼀下,对⽐的代码我会放在最后,可以看到两个⼀模⼀样的波只不过纵坐标轴的尺度不⼀样
channels=[0, ]每⼀次读取的数据都包含两个通道的信号可以设置为channels=[0, ]选择第⼀个信号,channels=[, 1]选择第⼆个信
号,channels=[0, 1]选择两个信号
好的我们解释清楚我们的每⼀个函数了直接运⾏pycharm运⾏效果如下,我们终于显⽰出了⼀个⼼电信号波形
到这就完成⼼电信号显⽰的hello-world
四.MIT-BIH 数据集中值滤波
好了读取完⼼电信号数据,我们就要把他扔到滤波器⾥,为了让⼤家更好的理解⾥⾯的细节我们分部分讲解
4.1准备部分代码
import wfdb
import matplotlib.pyplot as plt
from scipy.signal import medfilt
fliter =int(0.8*360)
男生的英语名字