如何过滤心电图和检测 R 峰值

信息处理 过滤器 心电图
2022-01-30 02:36:05

我正在尝试从原始 ECG 数据中提取 R 峰值,并且某些样本似乎受到 EMG 的干扰。我用了biosppy提供的lib和python,biosppy.signal.ecg,好像这个lib有,

  1. 默认滤波器是带有 filtfilt 的 firwin,模式是带通 3-45Hz,滤波器阶数是 0.3 * sample_rate,在我的例子中,sample_rate 是 500Hz,阶数是 150
  2. R 峰提取算法是 PS Hamilton,《开源心电图分析软件文档》,EPLimited,2002

在处理一些受 EMG 干扰的样本时,结果似乎不稳定, 在此处输入图像描述

在 2 到 8 之间,R 峰似乎不正确。我不熟悉 DSP,我该怎么做才能从合成信号中获取原始 ECG?

我尝试了什么(我阅读了一些关于心电图过滤的论文)和遇到的问题,

  • Baseline Wander,一些论文建议使用带有高通滤波器的firwin来去除这种噪声,频率可以是0.5Hz,我用firwin和butter都试过了,滤波后的信号比以前更平滑,但EMG仍然受到干扰存在
  • 电力线干扰,大多数情况下带阻频率为50Hz或60Hz,由于firwin使用的频率从0.5Hz到45Hz,这种噪声也被过滤掉了
  • EMG 噪声,一些论文提到使用移动平均来消除这种噪声,因为这种噪声很复杂并且可能与原始 ECG 重叠,有人建议使用 8 窗口移动平均。但在我的情况下,噪声持续很长时间,样本很多,即使窗口设置为 150,EMG 也存在

我想要的是在没有干扰的情况下获得陈旧的 R 峰?如果 EMG 不容易去除,我可以去除无效的 R 峰值并在检测到 R 峰值后进行插值,例如,

如果检测到的 R 峰是,

[439, 433, 433, 245, 193, 150, 414, 307, 135, 300, 432, 430, 429]

The first 3 and last 3 indices seem to be correct with the correct raw PQRST wave, but other indices are the invalid ones interfered by EMG, remove these indices, and insert 3 new indices with the value 433?

感谢您的热心帮助。

1个回答

你应该使用py-ecg-detectors Siply install 通过做

pip install py-ecg-detectors

然后您可以使用例如众所周知的 Pan Tompkins 算法来找到 R 峰

在这里,我使用了来自呼吸暂停心电图数据库的心电图记录

from ecgdetectors import Detectors
import matplotlib.pyplot as plt
import pandas as pd
fs=100 # sample freq

heartbeat = pd.read_csv("/myworkdir/mitbih-database/100.csv")

detectors = Detectors(fs)

r_peaks_pan = detectors.pan_tompkins_detector(heartbeat.iloc[:,2][0:1000])
r_peaks_pan= np.asarray(r_peaks_pan)

plt.plot(heartbeat.iloc[:,2][0:1000])
plt.plot(r_peaks_pan,heartbeat.iloc[:,2][0:1000][r_peaks_pan], 'ro')

具有 R 峰的心电图

如果需要,还可以添加 R 峰值校正算法:

def R_correction(signal, peaks):

    num_peak=peaks.shape[0]
    peaks_corrected_list=list()
    for index in range(num_peak):
        i=peaks[index]
        cnt=i
        if cnt-1<0:
            break
        if signal[cnt]<signal[cnt-1]:
            while signal[cnt]<signal[cnt-1]:
                cnt-=1
                if cnt<0:
                    break
        elif signal[cnt]<signal[cnt+1]:
            while signal[cnt]<signal[cnt+1]:
                cnt+=1
                if cnt<0:
                    break
        peaks_corrected_list.append(cnt)
    peaks_corrected=np.asarray(peaks_corrected_list)            
    return peaks_corrected 
corrected_R_peak=R_correction(heartbeat.iloc[:,2][0:1000],r_peaks_pan)
plt.plot(heartbeat.iloc[:,2][0:1000])
plt.plot(corrected_R_peak,heartbeat.iloc[:,2][0:1000][corrected_R_peak], 'ro')

校正的 R 峰