1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| import numpy as np from scipy import signal as sig
class EarEEGDistractionDetector: """ 单通道耳道EEG驾驶员分心检测 论文核心: bioRxiv 2026.01.24.701469 关键指标: frontal theta升高 + alpha降低 = 认知分心 优势: - 单通道(耳道放置),无需全头皮电极 - 非侵入式,可集成到耳机/头枕 - 实时计算,延迟<100ms """ def __init__(self, fs=250): self.fs = fs self.bands = { 'theta': (4, 8), 'alpha': (8, 13), 'beta': (13, 30), } self.window_size = int(4 * fs) self.threshold = 1.5 def compute_psd(self, eeg_signal): """ 计算功率谱密度 Args: eeg_signal: shape=(N,), 单通道EEG Returns: freqs, psd: 频率和功率 """ freqs, psd = sig.welch(eeg_signal, self.fs, nperseg=self.window_size) return freqs, psd def band_power(self, freqs, psd, band): """计算指定频段的平均功率""" f_low, f_high = band mask = (freqs >= f_low) & (freqs <= f_high) return np.mean(psd[mask]) if np.any(mask) else 0 def compute_theta_alpha_ratio(self, eeg_signal): """ 计算 theta/alpha 比值 这是分心检测的核心指标: - 比值升高 → 认知负荷增加 → 可能分心 - 比值降低 → 放松状态 → 正常驾驶 Args: eeg_signal: 4秒EEG窗口, shape=(1000,) @250Hz Returns: ratio: theta/alpha功率比值 is_distracted: 是否分心 """ freqs, psd = self.compute_psd(eeg_signal) theta_power = self.band_power(freqs, psd, self.bands['theta']) alpha_power = self.band_power(freqs, psd, self.bands['alpha']) ratio = theta_power / (alpha_power + 1e-10) is_distracted = ratio > self.threshold return ratio, is_distracted def sliding_window_detect(self, eeg_stream, step_sec=1): """ 滑动窗口实时检测 Args: eeg_stream: 连续EEG信号 step_sec: 步长(秒) Returns: results: [(time_sec, ratio, is_distracted), ...] """ step = int(step_sec * self.fs) results = [] for i in range(0, len(eeg_stream) - self.window_size, step): window = eeg_stream[i:i + self.window_size] ratio, distracted = self.compute_theta_alpha_ratio(window) t = i / self.fs results.append((t, ratio, distracted)) return results
if __name__ == "__main__": detector = EarEEGDistractionDetector(fs=250) np.random.seed(42) t = np.linspace(0, 10, 2500) normal_eeg = ( 5 * np.sin(2 * np.pi * 10 * t) + 1 * np.sin(2 * np.pi * 6 * t) + 0.5 * np.random.randn(2500) ) distracted_eeg = ( 1 * np.sin(2 * np.pi * 10 * t) + 5 * np.sin(2 * np.pi * 6 * t) + 0.5 * np.random.randn(2500) ) ratio_normal, _ = detector.compute_theta_alpha_ratio(normal_eeg[:1000]) ratio_distract, _ = detector.compute_theta_alpha_ratio(distracted_eeg[:1000]) print(f"正常驾驶 theta/alpha: {ratio_normal:.3f} (阈值 {detector.threshold})") print(f"分心驾驶 theta/alpha: {ratio_distract:.3f} (阈值 {detector.threshold})")
|