实战:心电图信号处理
实战:心电图信号处理
做这个小项目的想法来源于 HPC WEEK 比赛中 CT 图像并行计算的那道题。当时虽然我看不懂题目,但是大受震撼。因为不管是各种OJ还是Leetcode上我平时都不太会看到实际数据的处理,一般都是想象出来的场景,选择合适的算法和数据结构解决(毕竟以我们这种水平也做不了什么复杂的现实场景的东西)。
我后来问了下GPT,了解到了信号处理这个方向。打算从最基础的心电图信号处理做一个小项目进行实战。
环境配置
在项目文件夹下用venv创建python3.12环境,然后安装了numpy,scipy,matplotlib,wfdb库。
1 | pip install numpy scipy matplotlib wfdb |
其中:
wfdb:读 MIT-BIH 这类心电数据库
scipy:滤波、信号处理
matplotlib:画图
选择数据
我这里选了编号为100这个病人的数据(也就是第一个病人)。
wfdb.rdrecord() 是 WFDB 库的核心函数,用于读取生理信号记录(如 ECG 心电信号)。它返回一个record对象:
1 | record.p_signal # 生理信号数据(numpy 数组) |
其中,record.p_signal是存储生理信号数据的 numpy 数组,通常为 (样本数, 通道数)
MLII (Modified Limb Lead II),是第1个通道,是最常用的监测导联。问GPT后说这个最常用,所以我就取了这个。
给原始数据画图
创建一个时间轴t,用signal采样点的序号除以频率(1/周期),就是该采样点的时间。
1 | t = [i/fs for i in range(len(signal))] |
再画前五秒的图:
1 | plt.figure() |
去噪
带通滤波
带通滤波只保留需要的频段,这里我保留0.5–40 Hz的频段。Google后就可以知道,< 0.5 Hz的低频是基线漂移噪声,> 40 Hz的是肌电漂移。
1 | b, a = butter(order, [low/nyq, high/nyq], btype='band') |
这个是巴特沃斯带通滤波器,
陷波滤波
去除50Hz的工频干扰
1 | def notch_filter(x, fs, f0=50, Q=30): |