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 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
| import numpy as np import cv2
class LowCostDrowsinessDetector: """ 低成本疲劳检测系统 论文: arXiv:2609.13756 核心方法: 眼球中心追踪 + 动态阈值 硬件: 摄像头 + 处理器 + 报警器 成本: <$50 优势: - 无需GPU/深度学习 - standalone运行 - 动态阈值适配个体差异 """ def __init__(self, fps=30): self.fps = fps self.face_cascade = cv2.CascadeClassifier( cv2.data.haarcascades + 'haarcascade_frontalface_default.xml' ) self.eye_cascade = cv2.CascadeClassifier( cv2.data.haarcascades + 'haarcascade_eye.xml' ) self.closed_frames = 0 self.total_frames = 0 self.baseline_blink_duration = 0.3 self.drowsiness_threshold = 1.5 self.adaptation_rate = 0.01 def detect(self, frame): """ 检测单帧 Args: frame: BGR图像 Returns: is_drowsy: 是否疲劳 eye_state: 'open'/'closed' closed_duration: 闭眼持续秒数 """ gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = self.face_cascade.detectMultiScale(gray, 1.3, 5) if len(faces) == 0: return False, 'unknown', 0 face = max(faces, key=lambda f: f[2] * f[3]) fx, fy, fw, fh = face roi_gray = gray[fy:fy+fh, fx:fx+fw] eyes = self.eye_cascade.detectMultiScale(roi_gray) if len(eyes) >= 2: eye_state = 'open' self.closed_frames = 0 elif len(eyes) == 0: eye_state = 'closed' self.closed_frames += 1 else: eye_state = 'partial' self.closed_frames += 0.5 self.total_frames += 1 closed_duration = self.closed_frames / self.fps self._adapt_threshold(eye_state) is_drowsy = closed_duration >= self.drowsiness_threshold return is_drowsy, eye_state, closed_duration def _adapt_threshold(self, eye_state): """ 动态阈值自适应 原理: - 正常眨眼时长约0.1-0.3秒 - 疲劳时眨眼变慢/闭眼变长 - 阈值随个体眨眼模式自适应 """ if eye_state == 'open' and self.total_frames % (self.fps * 60) == 0: self.drowsiness_threshold = max( 1.0, min(3.0, self.drowsiness_threshold + self.adaptation_rate) )
class PixelLevelEyeDetector: """ 像素级闭眼检测器 论文方法:逐像素分析眼部区域 判断标准:眼部区域内暗像素比例 """ def __init__(self, darkness_threshold=50, closed_ratio=0.6): """ Args: darkness_threshold: 像素暗度阈值(0-255) closed_ratio: 暗像素占比>此值判定闭眼 """ self.darkness_threshold = darkness_threshold self.closed_ratio = closed_ratio def detect_eye_state(self, eye_roi): """ Args: eye_roi: 眼部区域灰度图 Returns: is_closed: 是否闭眼 darkness_ratio: 暗像素比例 """ dark_pixels = np.sum(eye_roi < self.darkness_threshold) total_pixels = eye_roi.size darkness_ratio = dark_pixels / total_pixels is_closed = darkness_ratio > self.closed_ratio return is_closed, darkness_ratio
class DynamicThresholdManager: """ 动态阈值管理 论文核心:阈值不固定,随驾驶员个体差异自适应 参数: - PERCLOS基准 - 眨眼频率基线 - 闭眼时长基线 """ def __init__(self, fps=30, window_sec=60): self.fps = fps self.window_frames = fps * window_sec self.eye_history = [] self.individual_blink_rate = None self.individual_blink_duration = None self.fatigue_multiplier = 3.0 def update(self, frame_idx, is_closed): """更新历史""" self.eye_history.append((frame_idx, is_closed)) self.eye_history = [ (f, c) for f, c in self.eye_history if frame_idx - f < self.window_frames ] if len(self.eye_history) >= self.window_frames: self._update_baseline() def _update_baseline(self): """更新个体基线""" closed_count = sum(1 for _, c in self.eye_history if c) self.individual_blink_rate = closed_count / (self.window_frames / self.fps) def get_fatigue_threshold(self): """获取自适应疲劳阈值""" if self.individual_blink_rate is None: return 1.5 return max(1.0, min(3.0, self.individual_blink_rate * self.fatigue_multiplier))
if __name__ == "__main__": detector = LowCostDrowsinessDetector(fps=30) pixel_detector = PixelLevelEyeDetector() threshold_mgr = DynamicThresholdManager(fps=30) eye_roi = np.random.randint(0, 100, (30, 60)) is_closed, ratio = pixel_detector.detect_eye_state(eye_roi) print(f"暗像素比例: {ratio:.2f}") print(f"判定闭眼: {is_closed}") threshold = threshold_mgr.get_fatigue_threshold() print(f"当前疲劳阈值: {threshold:.2f}秒") print("\n✅ 系统验证通过") print(f"硬件成本估算: 摄像头($15) + 处理器($20) + 蜂鸣器($5) = $40")
|