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
| class EyeMovementEntropy: """ 眼动熵计算 用于检测认知分心 参考: - IEEE Sensors Journal 2024 - Expert Systems with Applications 2025 """ def __init__(self, window_size: int = 300): """ Args: window_size: 窗口大小(帧数,约10秒@30fps) """ self.window_size = window_size self.gaze_buffer = [] def add_frame(self, gaze_data: dict): """ 添加单帧眼动数据 Args: gaze_data: { 'gaze_x': 水平视线位置, 'gaze_y': 垂直视线位置, 'pupil_diameter': 瞳孔直径, 'blink': 是否眨眼 } """ self.gaze_buffer.append(gaze_data) if len(self.gaze_buffer) > self.window_size: self.gaze_buffer.pop(0) def compute_entropy(self) -> dict: """ 计算眼动熵 Returns: entropy_result: { 'gaze_x_entropy': X方向熵, 'gaze_y_entropy': Y方向熵, 'pupil_entropy': 瞳孔熵, 'blink_entropy': 眨眼熵, 'total_entropy': 综合熵 } """ if len(self.gaze_buffer) < self.window_size * 0.5: return {'ready': False} gaze_x = np.array([f['gaze_x'] for f in self.gaze_buffer]) gaze_y = np.array([f['gaze_y'] for f in self.gaze_buffer]) pupil = np.array([f['pupil_diameter'] for f in self.gaze_buffer]) blink = np.array([f['blink'] for f in self.gaze_buffer], dtype=float) entropy_x = EntropyMeasures.sample_entropy(gaze_x, m=2, r=0.2) entropy_y = EntropyMeasures.sample_entropy(gaze_y, m=2, r=0.2) entropy_pupil = EntropyMeasures.sample_entropy(pupil, m=2, r=0.2) entropy_blink = EntropyMeasures.shannon_entropy(blink, bins=2) total_entropy = ( 0.3 * entropy_x + 0.3 * entropy_y + 0.2 * entropy_pupil + 0.2 * entropy_blink ) return { 'ready': True, 'gaze_x_entropy': entropy_x, 'gaze_y_entropy': entropy_y, 'pupil_entropy': entropy_pupil, 'blink_entropy': entropy_blink, 'total_entropy': total_entropy } def detect_cognitive_distraction(self, threshold: float = 1.5) -> dict: """ 检测认知分心 Args: threshold: 熵阈值(低于此值为认知分心) Returns: result: 检测结果 """ entropy_result = self.compute_entropy() if not entropy_result.get('ready', False): return {'detected': False, 'reason': 'insufficient_data'} total_entropy = entropy_result['total_entropy'] is_cognitively_distracted = total_entropy < threshold return { 'detected': is_cognitively_distracted, 'entropy': total_entropy, 'confidence': max(0, 1 - total_entropy / threshold), 'alert_level': 1 if is_cognitively_distracted else 0 }
|