为什么信号质量评估很重要?
脑电(EEG)信号本身非常微弱(通常在微伏级别),极易受到各种噪声源的干扰。低质量的数据会导致错误的实验结论、浪费宝贵的实验时间和科研资源。掌握信号质量评估方法,是每一位神经科学研究者的基本功。
本文将从信噪比计算、伪迹识别、阻抗检测和数据清洗四个维度,系统介绍EEG信号质量评估的方法。
实用的信号质量评估方法,帮助研究人员快速判断EEG数据是否可用,以及如何改善数据质量。
脑电(EEG)信号本身非常微弱(通常在微伏级别),极易受到各种噪声源的干扰。低质量的数据会导致错误的实验结论、浪费宝贵的实验时间和科研资源。掌握信号质量评估方法,是每一位神经科学研究者的基本功。
本文将从信噪比计算、伪迹识别、阻抗检测和数据清洗四个维度,系统介绍EEG信号质量评估的方法。
信噪比是衡量信号质量最核心的指标之一。以下是两种常用的计算方法:
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
def compute_snr_freq(eeg_data, fs, signal_band=(8, 13), noise_band=(30, 40)):
"""计算频域信噪比"""
freqs, psd = signal.welch(eeg_data, fs, nperseg=fs*2)
# 信号频段(例如Alpha频段8-13Hz)
sig_idx = np.logical_and(freqs >= signal_band[0], freqs <= signal_band[1])
sig_power = np.mean(psd[sig_idx])
# 噪声频段
noi_idx = np.logical_and(freqs >= noise_band[0], freqs <= noise_band[1])
noi_power = np.mean(psd[noi_idx])
snr = 10 * np.log10(sig_power / noi_power)
return snr
# 示例使用
snr_value = compute_snr_freq(eeg_channel, fs=500)
print(f"频域SNR: {snr_value:.2f} dB")
# SNR > 0dB 表示信号优于噪声,>3dB 表示质量良好
def compute_snr_temporal(eeg_data, segment_length=500):
"""通过分段计算时域SNR"""
n_segments = len(eeg_data) // segment_length
segments = eeg_data[:n_segments * segment_length].reshape(n_segments, -1)
signal_power = np.var(segments, axis=1)
noise_estimate = np.median(np.abs(np.diff(segments, axis=1)), axis=1) / 0.6745
noise_power = noise_estimate ** 2
snr = 10 * np.log10(np.mean(signal_power) / np.mean(noise_power))
return snr
质量判断标准:
常见的EEG伪迹包括眼电(EOG)伪迹、肌电(EMG)伪迹和运动伪迹:
import mne
# 使用ICA去除伪迹
ica = mne.preprocessing.ICA(n_components=15, random_state=42)
ica.fit(raw)
# 自动识别EOG伪迹
eog_indices, eog_scores = ica.find_bads_eog(raw, ch_name=['Fp1', 'Fp2'])
ica.exclude = eog_indices
# 应用ICA校正
raw_corrected = raw.copy()
ica.apply(raw_corrected)
电极与头皮之间的接触阻抗直接影响信号质量:
降低阻抗的技巧:
完整的数据清洗流程建议:
# 完整数据清洗流程示例
import mne
# 1. 读取原始数据
raw = mne.io.read_raw_edf('experiment.edf', preload=True)
# 2. 滤波
raw.filter(1, 40)
raw.notch_filter(50)
# 3. 自动检测坏通道
raw.info['bads'] = [] # 清空列表
bad_channels, _ = mne.preprocessing.find_bad_channels_maxwell(raw)
raw.info['bads'].extend(bad_channels)
print(f"坏通道: {raw.info['bads']}")
# 4. ICA去伪迹
ica = mne.preprocessing.ICA(n_components=20)
ica.fit(raw)
eog_indices, _ = ica.find_bads_eog(raw)
ica.exclude = eog_indices
raw_clean = ica.apply(raw.copy())
# 5. 分段
events = mne.find_events(raw_clean)
epochs = mne.Epochs(raw_clean, events, tmin=-0.2, tmax=0.8,
reject=dict(eeg=100e-6), # 拒绝振幅超过100μV的epoch
baseline=(-0.2, 0))
print(f"保留的epochs: {len(epochs)} / {len(events)}")