使用Python+TensorFlow2構建基於卷積神經網路(CNN)的ECG心電訊號識別分類(三)

還沒有女朋友的執念發表於2020-05-07

心電訊號的噪聲

EGG訊號具有微弱、低幅值、低頻、隨杋性的特點,很容易被噪聲干擾,而噪聲可能來自生物體內,如呼吸、肌肉顫抖,也可能因為接觸不良而引起體外干擾。是ECG訊號主要的三種噪聲為工頻干擾、肌電干擾和基線漂移3,也是在濾波過程中急需被抑制去除的噪聲干擾。

  • 工頻干擾:是由採集心電訊號的裝置周身的供電環境引起的電磁干擾,幅值低,噪聲頻率為50Hz左右,其波形很像一個正弦訊號,該噪聲常常會淹沒有用的心電訊號,也會影響P波和T波的檢測。

含工頻干擾的心電訊號

  • 肌電干擾:在心電圖採集過程中,因為人體運動肌肉不自主顫抖造成,這種干擾無規律可言,波形形態會急速變化,頻率很高,並且分佈很廣,範圍在0-2000Hz內,能量集中在30-300Hz內,持續時間一般為50ms,肌電干擾與心電訊號會重合在一起,這會導致有用的心電訊號細微的變化很可能被忽視。

含肌電干擾的心電訊號

  • 基線漂移:屬於低頻干擾,頻率分佈在0.15-0.3Hz內,由於電極位置的滑動變化或者人體的呼吸運動造成心電訊號隨時間緩慢變化而偏離正常基線位置產生基線漂移,幅度和頻率都會時刻變化著。心電訊號中的PR波段和ST波段非常容易受到影響產生失真。

含基線漂移干擾的心電訊號

心電訊號的預處理

小波變換(Wavelet Transform, WT)可以進行時頻變換,是對訊號進行時域以及頻域分析的最為理想工具。本文對含噪心電訊號採用基於小波變換的去噪處理方法,分為以下3個步驟:

  1. 由於噪聲和訊號混雜在一起,首先選擇一個小波基函式,由於噪聲和訊號混雜在一起,所以要用小波變換對含噪心電訊號進行某尺度分解得到各尺度上的小波係數。

  2. 心電訊號經過小波變換尺度分解後,幅值比較大的小波係數就是有用的訊號,幅值比較小的小波係數就是噪聲,根據心電訊號和夾雜噪聲的頻率分佈,對各尺度上的小波係數進行閾值處理,把小於閾值的小波係數置零或用閾值函式處理。

  3. 分別處理完小波尺度分解後的低頻係數和高頻係數,再重構訊號。

小波閾值去噪流程圖

4尺度小波分解所得各尺度係數示意圖如下,9尺度小波分解可以類比之:

四尺度小波分解示意圖

小波係數處理的閾值函式有硬閾值和軟閾值之分。

  1. 硬閾值函式:若分解後的係數絕對值大於閾值,保證其值不變;當其小於給定的閾值時,令其為零。

Snipaste_2020-05-06_23-59-38

  1. 軟閾值函式:若分解後的係數絕對值大於閾值,令其值減去λ;當其小於給定的閾值時,令其為零。

軟閾值法的閾值取值示意圖

其中w為原始小波係數,W為處理後的小波係數,λ為給定的閾值,N為訊號長度。λ的計算公式為
$$
\lambda=\frac{median|w|\sqrt{2lnN}}{0.6745}
$$

median為中位數

由上文分析可知,軟閾值去噪法的小波係數在連續性上優於硬閾值法,故本文采取了軟閾值法結合小波基對訊號進行模擬實驗。

關於小波變換的介紹可以參考這篇文章:https://blog.csdn.net/tbl1234567/article/details/52662985

程式碼實戰

去噪理論大致如此,下面來實戰編寫程式碼。以編號為100的心電資料記錄為例,上一篇文章已經通過wfdb將心電資料讀取到了record變數中,record為一個大小為(65000,1)的numpy陣列。要對其進行小波分解,首先要通過np.flatten()將其轉換為shape=(65000,)的陣列。

record = wfdb.rdrecord('ecg_data/' + 100, channel_names=['MLII'])
data = record.p_signal.flatten()

Python中使用pywt包進行訊號的時頻分析,其中包括傅立葉變換、小波變換等工具。使用pywt.wavedec()將時域訊號進行9尺度變換到頻域,小波基選用db5,返回值即為各尺度係數。

# 用db5作為小波基,對心電資料進行9尺度小波變換
coeffs = pywt.wavedec(data=data, wavelet='db5', level=9)
cA9, cD9, cD8, cD7, cD6, cD5, cD4, cD3, cD2, cD1 = coeffs

心電訊號9尺度分解係數

在對原始訊號進行分解之後,我們可以知道,1-2層的細節分量的能量與原始訊號的高頻干擾保持一致。表明1-2層是高頻噪聲(工頻干擾以及肌電噪聲)集中的主要地方。因此我們需要濾除D1層和D2層的細節分量,通過將其置0來達到去除的目的。然後將訊號分解得到的3~9層小波係數通過軟閾值公式對訊號的閾值進行處理。pywt.threshold()函式提供了閾值濾波功能,並且預設是mode='soft'的軟閾值濾波。

threshold = (np.median(np.abs(cD1)) / 0.6745) * (np.sqrt(2 * np.log(len(cD1))))
# 將高頻訊號cD1、cD2置零
cD1.fill(0)
cD2.fill(0)
# 將其他中低頻訊號按軟閾值公式濾波
for i in range(1, len(coeffs) - 2):
	coeffs[i] = pywt.threshold(coeffs[i], threshold)

最後對小波係數進行反變換,獲得去噪後的訊號。

rdata = pywt.waverec(coeffs=coeffs, wavelet='db5')

對預處理前後的100號訊號擷取前1500個訊號點進行對比如下,可以看出降噪效果還是不錯的:

plt.figure(figsize=(20, 4))
plt.plot(data)
plt.show()
plt.plot(rdata)
plt.show()

降噪處理前

降噪處理後

相關文章