You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python修复SciPy内置EKG数据集的基线漂移问题

修复EKG信号中的基线漂移问题(基于SciPy)

针对EKG信号的基线漂移(由人体运动等导致的低频基线波动),以下是几种实用的修复方法,基于SciPy或自定义实现:

1. 巴特沃斯高通滤波(医疗设备主流方案)

基线漂移属于低频干扰(通常<0.5Hz),高通滤波可直接剔除这类信号。使用SciPy的signal.butter设计巴特沃斯滤波器,配合filtfilt做零相位滤波,避免信号相位失真。

import numpy as np
import scipy.signal as signal
from scipy.datasets import electrocardiogram
import matplotlib.pyplot as plt

# 加载内置EKG数据,采样频率360Hz
ekg = electrocardiogram()
fs = 360

# 设计4阶巴特沃斯高通滤波器,截止频率0.5Hz
order = 4
cutoff = 0.5
nyq = 0.5 * fs
normal_cutoff = cutoff / nyq
b, a = signal.butter(order, normal_cutoff, btype='high', analog=False)

# 零相位滤波(避免信号偏移)
ekg_filtered = signal.filtfilt(b, a, ekg)

# 对比可视化
time = np.arange(ekg.size) / fs
plt.figure(figsize=(12, 6))
plt.subplot(2,1,1)
plt.plot(time, ekg, label='原始信号')
plt.title('原始EKG信号(含基线漂移)')
plt.subplot(2,1,2)
plt.plot(time, ekg_filtered, label='滤波后信号', color='red')
plt.title('去除基线漂移后的EKG信号')
plt.tight_layout()
plt.show()

2. 形态学开运算去除基线漂移

形态学开运算(先腐蚀后膨胀)能保留QRS波的尖锐峰值,同时提取缓慢变化的基线。用中值滤波近似实现,适合处理非平稳的基线突变。

import numpy as np
import scipy.signal as signal
from scipy.datasets import electrocardiogram
import matplotlib.pyplot as plt

ekg = electrocardiogram()
fs = 360

# 定义结构元素长度:覆盖QRS波宽度(取0.2s,对应72个采样点)
struct_len = int(0.2 * fs)

# 用中值滤波估计基线(忽略QRS波尖峰)
baseline = signal.medfilt(ekg, kernel_size=struct_len)

# 原始信号减去基线得到校正后信号
ekg_corrected = ekg - baseline

# 对比可视化
time = np.arange(ekg.size) / fs
plt.figure(figsize=(12,6))
plt.subplot(2,1,1)
plt.plot(time, ekg, label='原始信号')
plt.plot(time, baseline, label='估计基线', color='orange')
plt.legend()
plt.subplot(2,1,2)
plt.plot(time, ekg_corrected, label='校正后信号', color='red')
plt.legend()
plt.tight_layout()
plt.show()

3. 改进的滑动中位数基线估计

替换粗糙的移动平均为滑动窗口中位数(不受QRS波尖峰干扰),再用三次样条插值平滑基线,适合处理分段平稳的漂移。

import numpy as np
import scipy.signal as signal
from scipy.interpolate import CubicSpline
from scipy.datasets import electrocardiogram
import matplotlib.pyplot as plt

ekg = electrocardiogram()
fs = 360
# 取1秒窗口(覆盖多个心跳)
window_size = int(1.0 * fs)

# 计算滑动窗口中位数
baseline_est = []
for i in range(0, len(ekg), window_size):
    window = ekg[i:i+window_size]
    baseline_est.append(np.median(window))

# 三次样条插值得到平滑基线
x = np.arange(0, len(ekg), window_size)
x_full = np.arange(len(ekg))
cs = CubicSpline(x, baseline_est)
baseline_smooth = cs(x_full)

ekg_corrected = ekg - baseline_smooth

# 对比可视化
time = np.arange(ekg.size) / fs
plt.figure(figsize=(12,6))
plt.subplot(2,1,1)
plt.plot(time, ekg, label='原始信号')
plt.plot(time, baseline_smooth, label='平滑基线', color='orange')
plt.legend()
plt.subplot(2,1,2)
plt.plot(time, ekg_corrected, label='校正后信号', color='red')
plt.legend()
plt.tight_layout()
plt.show()

内容的提问来源于stack exchange,提问作者aero-man

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 14:35:43