MIT-BIH-AF房颤数据集实战:Python信号处理全流程解析

1. 环境准备与数据加载

处理MIT-BIH-AF数据集的第一步是搭建合适的Python环境。推荐使用Anaconda创建独立环境,避免库版本冲突:

conda create -n ecg python=3.8
conda activate ecg
pip install wfdb PyWavelets scipy matplotlib numpy

数据集文件通常包含三种关键格式:

  • .dat :存储原始ECG信号
  • .atr :包含医生标注的心律事件
  • .qrs :记录R峰位置信息

使用wfdb库加载数据的正确方式:

import wfdb

# 示例:加载患者04015的数据
record = wfdb.rdrecord('04015', pb_dir='afdb') 
annotations = wfdb.rdann('04015', 'atr', pb_dir='afdb')

常见问题排查表:

错误类型 可能原因 解决方案
FileNotFoundError 文件路径错误 确认PhysioNet文件结构
ValueError 文件格式不匹配 检查文件扩展名完整性
ImportError 依赖库缺失 重新安装wfdb库

提示:首次使用PhysioNet数据集需注册账号并签署数据使用协议

2. 信号可视化与基础分析

原始ECG信号通常包含多种噪声成分,需要先进行初步观察:

import matplotlib.pyplot as plt

plt.figure(figsize=(12,4))
plt.plot(record.p_signal[:2000,0])
plt.title('Raw ECG Signal (Lead I)')
plt.xlabel('Samples')
plt.ylabel('Amplitude (mV)')
plt.grid()
plt.show()

典型信号特征分析流程:

  1. 识别采样率 record.fs (通常为250Hz)
  2. 检查导联数 record.n_sig (MIT-BIH-AF为双导联)
  3. 提取时间轴 t = np.arange(len(ecg))/record.fs

关键统计指标计算:

import numpy as np

ecg = record.p_signal[:,0]
print(f"信号长度: {len(ecg)} samples")
print(f"持续时间: {len(ecg)/record.fs/60:.1f} minutes")
print(f"幅值范围: {np.min(ecg):.2f} ~ {np.max(ecg):.2f} mV")

3. 高级信号处理技术

3.1 小波去噪实战

PyWavelets提供多级小波分解能力,特别适合ECG信号处理:

import pywt

def wavelet_denoise(signal, wavelet='db4', level=3):
    coeffs = pywt.wavedec(signal, wavelet, level=level)
    sigma = np.median(np.abs(coeffs[-1]))/0.6745
    uthresh = sigma * np.sqrt(2*np.log(len(signal)))
    coeffs[1:] = [pywt.threshold(c, uthresh, mode='soft') for c in coeffs[1:]]
    return pywt.waverec(coeffs, wavelet)

去噪效果对比参数:

小波基 计算效率 保真度 适用场景
db4 常规ECG
sym5 极佳 高精度分析
haar 极高 实时处理

3.2 R峰检测优化

改进的Pan-Tompkins算法实现:

def detect_r_peaks(ecg, fs=250):
    # 带通滤波
    b = signal.firwin(31, [5, 15], fs=fs, pass_zero=False)
    filtered = signal.lfilter(b, 1, ecg)
    
    # 微分处理
    diff = np.diff(filtered, prepend=0)
    
    # 平方增强
    squared = diff ** 2
    
    # 移动平均
    window = int(0.15 * fs)
    integrated = np.convolve(squared, np.ones(window)/window, mode='same')
    
    # 峰值检测
    peaks, _ = signal.find_peaks(integrated, distance=0.6*fs)
    return peaks

4. 特征工程与模型输入构建

4.1 时域特征提取

典型RR间期特征计算方法:

def extract_rr_features(r_peaks, fs):
    rr_intervals = np.diff(r_peaks)/fs*1000  # 转换为毫秒
    features = {
        'mean_rr': np.mean(rr_intervals),
        'sdnn': np.std(rr_intervals),
        'rmssd': np.sqrt(np.mean(np.square(np.diff(rr_intervals)))),
        'nn50': sum(np.abs(np.diff(rr_intervals))>50),
        'pnn50': sum(np.abs(np.diff(rr_intervals))>50)/len(rr_intervals)*100
    }
    return features

4.2 频域分析实现

使用Welch方法计算功率谱密度:

from scipy import signal

def compute_psd(rr_intervals):
    f, pxx = signal.welch(rr_intervals, fs=4, nperseg=256)
    lf = np.trapz(pxx[(f>=0.04)&(f<0.15)])
    hf = np.trapz(pxx[(f>=0.15)&(f<0.4)])
    return {'lf': lf, 'hf': hf, 'lf_hf_ratio': lf/hf}

5. 完整处理流程示例

整合所有步骤的端到端处理管道:

# 1. 数据加载
record = wfdb.rdrecord('04015', pb_dir='afdb')
ecg = record.p_signal[:,0]

# 2. 信号预处理
denoised = wavelet_denoise(ecg)
detrended = signal.detrend(denoised)

# 3. 特征提取
r_peaks = detect_r_peaks(detrended, fs=record.fs)
rr_features = extract_rr_features(r_peaks, record.fs)
psd_features = compute_psd(np.diff(r_peaks)/record.fs)

# 4. 结果可视化
plt.figure(figsize=(10,6))
plt.plot(detrended[5000:7000])
plt.plot(r_peaks[(r_peaks>5000)&(r_peaks<7000)], 
         detrended[r_peaks[(r_peaks>5000)&(r_peaks<7000)]], 'rx')
plt.title('Processed ECG with R-peaks')
plt.show()

注意:实际应用中建议将处理过程封装为类,方便复用和管理状态

关键调试技巧:

  • 对于低质量信号,可调整小波去噪的阈值策略
  • R峰检测对滤波参数敏感,需根据具体设备调整
  • 长时间记录建议分块处理,避免内存溢出
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐