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
| """ 安全带误用检测系统架构 基于CUPRA Raval Euro NCAP 2026评测
检测能力: 1. 安全带扣合状态 (SBM-01) 2. 安全带后方佩戴 (SBM-02) ← Raval的核心优势 3. 后排安全带提醒全覆盖
技术方案推测: - 座椅压力传感器 → 乘员存在 - 安全带张力传感器 → 扣合状态 - B柱/A柱摄像头 → 安全带路径检测 - 安全带 buckle传感器 → 扣合确认 """
import numpy as np from typing import Tuple, List from dataclasses import dataclass
@dataclass class BeltStatus: """安全带状态""" is_buckled: bool is_worn_correctly: bool is_occupied: bool misuse_type: str confidence: float
class SeatbeltMisuseDetector: """ 安全带误用检测器 核心检测逻辑: 1. 座椅压力传感器确认乘员存在 2. Buckle传感器确认安全带扣合 3. 视觉检测安全带路径 4. 路径异常 → 误用告警 关键场景 - 安全带后方佩戴 (SBM-02): - 正确: 安全带跨过胸前,从左肩到右腰 - 误用: 安全带从身后绕过,未跨胸前 视觉检测关键: 安全带在胸前区域是否可见 """ def __init__(self): self.confirmation_frames = 3 self.misuse_count = 0 self.normal_count = 0 self.correct_path_points = [ "shoulder_anchor", "chest_crossing", "waist_anchor", "buckle", ] def detect_misuse(self, pressure_sensor: float, buckle_status: bool, belt_path_image: np.ndarray, chest_region_bbox: Tuple[int,int,int,int]) -> BeltStatus: """ 安全带误用检测主函数 Args: pressure_sensor: 座椅压力传感器读数 (kg) buckle_status: 安全带扣合状态 belt_path_image: B柱摄像头图像 chest_region_bbox: 胸前区域边界框 (x1,y1,x2,y2) Returns: BeltStatus: 安全带状态 """ is_occupied = pressure_sensor > 15.0 if not is_occupied: return BeltStatus(False, True, False, "empty", 1.0) if not buckle_status: return BeltStatus(False, False, True, "unbuckled", 1.0) x1, y1, x2, y2 = chest_region_bbox chest_region = belt_path_image[y1:y2, x1:x2] belt_in_chest = self._detect_belt_in_region(chest_region) if belt_in_chest: self.normal_count += 1 self.misuse_count = 0 misuse_type = "correct" confidence = 0.95 else: self.misuse_count += 1 self.normal_count = 0 if self.misuse_count >= self.confirmation_frames: misuse_type = "behind_back" confidence = 0.85 else: misuse_type = "checking" confidence = 0.5 return BeltStatus( is_buckled=True, is_worn_correctly=(misuse_type == "correct"), is_occupied=True, misuse_type=misuse_type, confidence=confidence ) def _detect_belt_in_region(self, region: np.ndarray) -> bool: """ 检测区域内是否有安全带 安全带特征: - 暗色带状区域 (RGB值低) - 斜向条带 (约30-60度) - 宽度约15-30像素 """ if region.size == 0: return False gray = np.mean(region, axis=2) if len(region.shape) == 3 else region dark_mask = gray < 80 h, w = gray.shape dark_ratio = np.sum(dark_mask) / (h * w) if dark_ratio > 0.15 and dark_ratio < 0.6: row_sums = np.sum(dark_mask, axis=1) col_sums = np.sum(dark_mask, axis=0) if np.std(row_sums) / (np.mean(row_sums) + 1e-6) > 0.5: return True return False
if __name__ == "__main__": detector = SeatbeltMisuseDetector() img_correct = np.random.randint(0, 255, (100, 100, 3), dtype=np.uint8) img_correct[40:55, 20:80, :] = 30 img_misuse = np.random.randint(100, 255, (100, 100, 3), dtype=np.uint8) print("=== 正确佩戴 ===") for i in range(5): result = detector.detect_misuse( pressure_sensor=70.0, buckle_status=True, belt_path_image=img_correct, chest_region_bbox=(0, 0, 100, 100) ) print(f"帧{i}: {result.misuse_type}, conf={result.confidence:.2f}") print("\n=== 后方佩戴 ===") detector2 = SeatbeltMisuseDetector() for i in range(5): result = detector2.detect_misuse( pressure_sensor=70.0, buckle_status=True, belt_path_image=img_misuse, chest_region_bbox=(0, 0, 100, 100) ) print(f"帧{i}: {result.misuse_type}, conf={result.confidence:.2f}")
|