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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
| import numpy as np from typing import Tuple
def detect_steering_reversals( steering_angle: np.ndarray, fps: int = 30, min_angle_change: float = 3.0, max_duration: float = 0.5, ) -> Tuple[np.ndarray, float]: """ 检测转向盘微修正(reversals) 基于Toyota IDD数据集发现的酒精特异性特征: 酒驾驾驶员会出现高频微小转向修正 Args: steering_angle: 转向角序列 (degrees), shape=(N,) fps: 采样率 min_angle_change: 最小角度变化阈值 max_duration: 持续时间上限 Returns: reversal_indices: 微修正位置索引 reversal_rate: 每分钟微修正次数 Example: >>> # 模拟酒驾数据(高频微修正) >>> np.random.seed(42) >>> angles = np.cumsum(np.random.normal(0, 0.5, 1800)) >>> # 加入微修正 >>> for i in range(0, 1800, 50): ... angles[i:i+5] += np.random.normal(0, 3, 5) >>> idx, rate = detect_steering_reversals(angles) >>> print(f"Reversal rate: {rate:.1f}/min") Reversal rate: 18.2/min """ diff = np.diff(steering_angle) sign_changes = np.where(np.diff(np.sign(diff)) != 0)[0] valid_reversals = [] for idx in sign_changes: window_size = int(max_duration * fps) start = max(0, idx - window_size) end = min(len(steering_angle), idx + window_size) angle_range = np.max(steering_angle[start:end]) - np.min(steering_angle[start:end]) if angle_range >= min_angle_change: valid_reversals.append(idx) valid_reversals = np.array(valid_reversals) duration_min = len(steering_angle) / (fps * 60) reversal_rate = len(valid_reversals) / duration_min if duration_min > 0 else 0 return valid_reversals, reversal_rate
def classify_impairment( steering_data: np.ndarray, gaze_entropy: float, pupil_diameter_var: float, speed_variance: float, ) -> dict: """ 基于IDD数据集发现的多模态损伤分类 使用掩蔽效应感知的融合策略: - 不依赖单一指标(避免掩蔽效应) - 转向微修正 → 酒驾特异 - 注视熵下降 → 通用损伤 - 瞳孔直径变异 → 认知负荷 - 速度方差 → 辅助(不可靠) Args: steering_data: 转向角序列 gaze_entropy: 注视分布熵 (0-1) pupil_diameter_var: 瞳孔直径方差 speed_variance: 速度方差 Returns: classification: { 'state': 'normal|alcohol|cognitive|combined', 'confidence': float, 'evidence': dict } """ _, reversal_rate = detect_steering_reversals(steering_data) alcohol_score = 0.0 cognitive_score = 0.0 if reversal_rate > 15.0: alcohol_score += 0.4 if gaze_entropy < 0.6: alcohol_score += 0.2 cognitive_score += 0.3 if pupil_diameter_var > 0.15: cognitive_score += 0.3 if speed_variance < 2.0: cognitive_score += 0.1 elif speed_variance > 8.0: alcohol_score += 0.1 if alcohol_score > 0.5 and cognitive_score > 0.4: state = 'combined' confidence = min(alcohol_score + cognitive_score, 0.95) elif alcohol_score > cognitive_score: state = 'alcohol' confidence = alcohol_score else: state = 'cognitive' confidence = cognitive_score return { 'state': state, 'confidence': confidence, 'evidence': { 'reversal_rate': reversal_rate, 'gaze_entropy': gaze_entropy, 'pupil_var': pupil_diameter_var, 'speed_var': speed_variance, 'alcohol_score': alcohol_score, 'cognitive_score': cognitive_score, } }
if __name__ == "__main__": np.random.seed(42) normal_steering = np.cumsum(np.random.normal(0, 0.3, 1800)) normal_result = classify_impairment( normal_steering, gaze_entropy=0.75, pupil_diameter_var=0.08, speed_variance=5.0 ) print(f"正常驾驶: {normal_result['state']} (conf={normal_result['confidence']:.2f})") drunk_steering = np.cumsum(np.random.normal(0, 0.3, 1800)) for i in range(0, 1800, 40): drunk_steering[i:i+5] += np.random.normal(0, 3, 5) drunk_result = classify_impairment( drunk_steering, gaze_entropy=0.55, pupil_diameter_var=0.10, speed_variance=9.0 ) print(f"酒驾: {drunk_result['state']} (conf={drunk_result['confidence']:.2f})") combined_result = classify_impairment( drunk_steering, gaze_entropy=0.50, pupil_diameter_var=0.20, speed_variance=4.5 ) print(f"酒驾+分心: {combined_result['state']} (conf={combined_result['confidence']:.2f})")
|