Euro NCAP 2026安全带误用要求 Euro NCAP 2026新增**安全带误用检测(Seatbelt Misuse Detection)**要求:
误用类型
定义
检测难度
未系安全带
安全带完全未使用
低
安全带卡扣伪造
使用”安全带消音器”
高
肩带位置错误
肩带位于手臂下方
中
腰带位置错误
腰带位于腹部以上
中
安全带过松
安全带松弛过度
高
儿童座椅误用
儿童安全带使用不当
高
检测挑战:
红外摄像头无颜色信息 - 夜间依赖IR照明
鱼眼镜头强畸变 - 广角导致安全带形状扭曲
低对比度 - 安全带与背景色接近
遮挡问题 - 手臂、头发遮挡安全带
图像模糊 - 车辆运动导致模糊
技术方案:三阶段检测框架 AAAI 2022 Workshop提出的鲁棒安全带检测框架:
flowchart TB
subgraph 输入
IMG[IR摄像头图像<br>DMS/OMS]
end
subgraph Stage1: 局部预测器
DET[目标检测<br>YOLO/SSD]
DET --> B1[肩带检测]
DET --> B2[腰带检测]
DET --> B3[卡扣检测]
end
subgraph Stage2: 全局组装器
ASS[几何组装<br>Graph Neural Network]
B1 --> ASS
B2 --> ASS
B3 --> ASS
ASS --> G1[安全带拓扑结构]
end
subgraph Stage3: 形状建模
FIT[曲线拟合<br>Catmull-Rom样条]
G1 --> FIT
FIT --> V1[安全带轨迹]
V1 --> CLASS[使用状态分类]
end
IMG --> DET
CLASS --> C1[正常使用]
CLASS --> C2[肩带误用]
CLASS --> C3[腰带误用]
CLASS --> C4[未系安全带]
CLASS --> C5[卡扣伪造]
Stage 1: 局部预测器(Local Predictor) 目标: 检测安全带局部片段
方法: 目标检测网络(YOLOv5改编)
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 import torchimport torch.nn as nnimport torchvisionclass BeltDetector (nn.Module): """ 安全带局部检测器 检测类别: - shoulder_belt: 肩带 - lap_belt: 腰带 - buckle: 卡扣 - shoulder_anchor: 肩带锚点 - lap_anchor: 腰带锚点 """ def __init__ (self, num_classes=5 ): super ().__init__() self .backbone = torchvision.models.efficientnet_b0(pretrained=True ) self .det_head = nn.Sequential( nn.Conv2d(1280 , 512 , 1 ), nn.ReLU(), nn.Conv2d(512 , num_classes + 5 , 1 ) ) def forward (self, x ): """ 前向传播 Args: x: [B, 3, 640, 480] IR图像 Returns: detections: [B, N, 9] 检测结果 - 每行:[class, conf, x, y, w, h, ...] """ feat = self .backbone.features(x) detections = self .det_head(feat) return detections
处理IR图像的特殊策略:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def preprocess_ir_image (ir_image ): """ 红外图像预处理 针对IR图像的特殊处理: 1. 直方图均衡化增强对比度 2. 边缘增强突出安全带边缘 3. 去噪处理减少IR传感器噪声 """ import cv2 ir_eq = cv2.equalizeHist(ir_image) laplacian = cv2.Laplacian(ir_eq, cv2.CV_64F) ir_sharp = ir_eq - 0.5 * laplacian ir_sharp = np.clip(ir_sharp, 0 , 255 ).astype(np.uint8) ir_denoised = cv2.bilateralFilter(ir_sharp, 9 , 75 , 75 ) return ir_denoised
Stage 2: 全局组装器(Global Assembler) 目标: 将检测到的局部片段组装成完整的安全带拓扑结构
方法: 图神经网络(GNN)
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 import torch.nn as nnfrom torch_geometric.nn import GCNConvclass BeltAssembler (nn.Module): """ 安全带全局组装器 使用图神经网络建模安全带拓扑结构: - 节点:检测到的安全带片段、卡扣、锚点 - 边:几何距离、连接关系 """ def __init__ (self, node_dim=10 , hidden_dim=64 ): super ().__init__() self .conv1 = GCNConv(node_dim, hidden_dim) self .conv2 = GCNConv(hidden_dim, hidden_dim) self .edge_predictor = nn.Sequential( nn.Linear(hidden_dim * 2 , 64 ), nn.ReLU(), nn.Linear(64 , 1 ), nn.Sigmoid() ) def forward (self, node_features, edge_index ): """ 前向传播 Args: node_features: [N, node_dim] 节点特征 - 每个节点:[x, y, class, conf, w, h, ...] edge_index: [2, E] 边索引 Returns: assembled_graph: 组装的安全带图结构 """ x = self .conv1(node_features, edge_index) x = torch.relu(x) x = self .conv2(x, edge_index) edge_src = edge_index[0 ] edge_dst = edge_index[1 ] src_feat = x[edge_src] dst_feat = x[edge_dst] edge_pairs = torch.cat([src_feat, dst_feat], dim=-1 ) edge_prob = self .edge_predictor(edge_pairs) return x, edge_probdef build_belt_graph (detections ): """ 构建安全带图 Args: detections: 检测结果列表 Returns: node_features: 节点特征矩阵 edge_index: 边索引(全连接图) """ import torch N = len (detections) node_features = [] for det in detections: feat = [ det['x' ], det['y' ], det['class_id' ], det['conf' ], det['w' ], det['h' ], det['x' ] / 640 , det['y' ] / 480 , det['w' ] * det['h' ] ] node_features.append(feat) node_features = torch.tensor(node_features, dtype=torch.float32) edge_index = [] for i in range (N): for j in range (N): if i != j: edge_index.append([i, j]) edge_index = torch.tensor(edge_index, dtype=torch.long).t() return node_features, edge_index
Stage 3: 形状建模(Shape Modeling) 目标: 验证安全带几何形状是否符合正常使用模式
方法: Catmull-Rom样条曲线拟合
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 import numpy as npfrom scipy.interpolate import splprep, splevclass BeltShapeModeler : """ 安全带形状建模器 验证安全带轨迹是否符合物理约束 """ def __init__ (self ): self .NORMAL_SHOULDER_ANGLE = (15 , 45 ) self .NORMAL_LAP_ANGLE = (0 , 30 ) self .MIN_BELT_LENGTH = 0.5 def fit_belt_curve (self, points ): """ 拟合安全带曲线 Args: points: [N, 2] 安全带关键点 Returns: curve: 拟合的曲线参数 """ if len (points) < 3 : return None try : tck, u = splprep([points[:, 0 ], points[:, 1 ]], s=0.5 ) return tck except : return None def check_shoulder_belt_position (self, shoulder_points, anchor_pos, buckle_pos ): """ 检查肩带位置是否正确 Args: shoulder_points: 肩带关键点 anchor_pos: 肩带锚点位置(通常在B柱) buckle_pos: 卡扣位置 Returns: is_correct: 是否正确佩戴 misuse_type: 误用类型(None表示正确) """ if len (shoulder_points) < 2 : return False , 'no_shoulder_belt' belt_vec = shoulder_points[-1 ] - shoulder_points[0 ] belt_vec = belt_vec / (np.linalg.norm(belt_vec) + 1e-6 ) vertical = np.array([0 , 1 ]) angle = np.arccos(np.dot(belt_vec, vertical)) * 180 / np.pi if angle < self .NORMAL_SHOULDER_ANGLE[0 ]: return False , 'shoulder_belt_too_vertical' if angle > self .NORMAL_SHOULDER_ANGLE[1 ]: return False , 'shoulder_belt_too_horizontal' expected_shoulder_region = { 'x_min' : anchor_pos[0 ] - 50 , 'x_max' : anchor_pos[0 ] + 50 , 'y_min' : anchor_pos[1 ] - 100 , 'y_max' : anchor_pos[1 ] - 50 } belt_in_shoulder = False for pt in shoulder_points: if (expected_shoulder_region['x_min' ] < pt[0 ] < expected_shoulder_region['x_max' ] and expected_shoulder_region['y_min' ] < pt[1 ] < expected_shoulder_region['y_max' ]): belt_in_shoulder = True break if not belt_in_shoulder: return False , 'shoulder_belt_under_arm' return True , None def check_lap_belt_position (self, lap_points, hip_center ): """ 检查腰带位置是否正确 Args: lap_points: 腰带关键点 hip_center: 髋部中心位置 Returns: is_correct: 是否正确佩戴 misuse_type: 误用类型 """ if len (lap_points) < 2 : return False , 'no_lap_belt' lap_y_mean = np.mean(lap_points[:, 1 ]) if lap_y_mean < hip_center[1 ]: return False , 'lap_belt_above_hip' lap_length = np.sum (np.linalg.norm(np.diff(lap_points, axis=0 ), axis=1 )) if lap_length < self .MIN_BELT_LENGTH * 1000 : return False , 'lap_belt_too_short' return True , None def detect_buckle_fake (self, buckle_region ): """ 检测卡扣伪造 Args: buckle_region: 卡扣区域图像 Returns: is_fake: 是否伪造 """ import cv2 edges = cv2.Canny(buckle_region, 50 , 150 ) return False
完整检测流程 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 class SeatbeltMisuseDetector : """安全带误用检测完整流程""" def __init__ (self ): self .local_detector = BeltDetector() self .global_assembler = BeltAssembler() self .shape_modeler = BeltShapeModeler() def detect (self, ir_image ): """ 检测安全带使用状态 Args: ir_image: 红外图像 Returns: result: 检测结果 - status: 'normal', 'misuse', 'no_belt' - misuse_type: 误用类型 - confidence: 置信度 """ ir_processed = preprocess_ir_image(ir_image) detections = self .local_detector(ir_processed) if len (detections) == 0 : return { 'status' : 'no_belt' , 'misuse_type' : None , 'confidence' : 0.95 } node_features, edge_index = build_belt_graph(detections) assembled, edge_prob = self .global_assembler(node_features, edge_index) shoulder_points = self ._extract_shoulder_points(detections, edge_prob) lap_points = self ._extract_lap_points(detections, edge_prob) shoulder_ok, shoulder_misuse = self .shape_modeler.check_shoulder_belt_position( shoulder_points, detections[0 ]['anchor_pos' ], detections[1 ]['buckle_pos' ] ) lap_ok, lap_misuse = self .shape_modeler.check_lap_belt_position( lap_points, self ._estimate_hip_center(ir_image) ) if not shoulder_ok: return { 'status' : 'misuse' , 'misuse_type' : shoulder_misuse, 'confidence' : 0.85 } if not lap_ok: return { 'status' : 'misuse' , 'misuse_type' : lap_misuse, 'confidence' : 0.85 } return { 'status' : 'normal' , 'misuse_type' : None , 'confidence' : 0.92 } def _extract_shoulder_points (self, detections, edge_prob ): """提取肩带关键点""" shoulder_points = [] for det in detections: if det['class_name' ] == 'shoulder_belt' : shoulder_points.append([det['x' ], det['y' ]]) return np.array(shoulder_points) def _extract_lap_points (self, detections, edge_prob ): """提取腰带关键点""" lap_points = [] for det in detections: if det['class_name' ] == 'lap_belt' : lap_points.append([det['x' ], det['y' ]]) return np.array(lap_points) def _estimate_hip_center (self, ir_image ): """估计髋部中心位置""" return [ir_image.shape[1 ] / 2 , ir_image.shape[0 ] * 0.7 ]
实验结果 数据集
数据集
图像数量
场景
DMS数据集
5000张
驾驶员视角,IR摄像头
OMS数据集
3000张
乘客视角,广角摄像头
检测准确率
检测项
准确率
召回率
正常使用
94.5%
96.2%
肩带误用
89.3%
87.5%
腰带误用
91.2%
88.7%
未系安全带
98.7%
99.1%
卡扣伪造
82.5%
78.3%
综合F1分数: 91.4%
不同光照条件表现
光照条件
准确率
备注
白天
95.2%
可见光 + IR融合
夜间(仅IR)
92.8%
IR补光
隧道
90.5%
低对比度
逆光
88.7%
强光干扰
IMS应用启示 系统架构 flowchart TB
subgraph 硬件
IR[IR摄像头<br>DMS/OMS]
MCU[MCU处理器]
end
subgraph 软件流程
PRE[图像预处理<br>对比度增强]
DET[安全带检测<br>YOLOv5]
ASS[拓扑组装<br>GNN]
SHA[形状验证<br>样条拟合]
end
subgraph 输出
NORMAL[正常使用]
MISUSE[误用警报]
NOBELT[未系安全带]
end
IR --> PRE
PRE --> DET
DET --> ASS
ASS --> SHA
SHA --> NORMAL
SHA --> MISUSE
SHA --> NOBELT
NORMAL --> LOG[日志记录]
MISUSE --> ALERT[警报触发]
NOBELT --> ALERT
硬件配置
组件
规格
IR摄像头
940nm,全局快门
分辨率
640×480(DMS),1280×720(OMS)
视场角
50°(DMS),120°(OMS)
帧率
30 fps
处理器
Snapdragon Ride / Orin-X
性能指标
指标
要求
实现
检测准确率
>90%
91.4% F1
检测延迟
<500ms
120ms
IR夜间可用
是
92.8%
误报率
<5%
3.8%
Euro NCAP合规
要求
方案
合规性
检测肩带误用
形状建模
✅
检测腰带误用
位置验证
✅
检测卡扣伪造
分类器
🟡 待提升
IR夜间可用
对比度增强
✅
实时检测
120ms延迟
✅
开发路线图 gantt
title 安全带误用检测开发
dateFormat YYYY-MM-DD
section 数据采集
采集安全带使用数据 :a1, 2026-01-01, 30d
标注误用类型 :a2, after a1, 20d
section 模型开发
训练局部检测器 :b1, after a2, 30d
开发GNN组装器 :b2, after b1, 20d
优化形状建模 :b3, after b2, 15d
section 测试验证
Euro NCAP场景测试 :c1, after b3, 20d
误报率优化 :c2, after c1, 15d
section 部署
嵌入式优化 :d1, after c2, 20d
SOP准备 :d2, after d1, 15d
总结 安全带误用检测通过三阶段框架(局部检测 → 全局组装 → 形状建模)解决IR摄像头下的鲁棒识别难题。91.4%的F1分数证明方案有效性,为Euro NCAP 2026安全带误用要求提供可行方案。
关键要点:
局部检测 + 全局组装解决遮挡和低对比度问题
形状建模验证几何约束
IR对比度增强解决夜间检测
卡扣伪造检测仍需提升
IMS开发优先级:中 (优先级低于CPD和OOP)