安全带误用检测技术路线:从简单检测到误用分类 | IMS落地指南

背景

Euro NCAP 2026 OMS 协议新增安全带状态检测要求,包括:未系安全带、安全带错误佩戴(误用)。传统安全带检测仅判断”系/未系”,但 NCAP 2026 要求识别误用模式:安全带在身后、安全带夹在腋下、安全带未锁扣等。

安全带状态分类

六类安全带状态

类别 描述 检测难度 Euro NCAP 要求
正常佩戴 肩带跨胸前,腰带跨骨盆 ✅ 易 必须
未系 无安全带 ✅ 易 必须
身后佩戴 安全带绕到身后 ⚠️ 中 2026新增
腋下佩戴 肩带从腋下穿过 ⚠️ 中 2026新增
未锁扣 安全带拉出但未插入扣环 ⚠️ 中 2026新增
儿童座椅干扰 安全带与儿童座椅缠绕 ❌ 难 未来

检测技术路线对比

方案 输入 优势 劣势 误用检测
安全带锁扣传感器 机械信号 100%可靠(系/未系) ❌ 无法检测误用 ❌
摄像头视觉 RGB/NIR图像 可检测误用模式 受遮挡/光照影响 ✅
深度相机ToF 深度图 可检测3D位置 成本较高 ✅
视觉+锁扣融合 多传感器 最可靠 系统复杂 ✅

视觉检测算法

1. 安全带检测网络

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
"""
安全带检测与误用分类网络

目标: 从车内摄像头图像检测安全带状态
分类: 6类 (正常/未系/身后/腋下/未锁扣/儿童干扰)

模型: 轻量级目标检测 + 关键点估计
"""

import torch
import torch.nn as nn

class SeatbeltDetector(nn.Module):
"""
安全带检测器

架构:
1. 骨干网络: MobileNetV3-Small (轻量)
2. 检测头: 安全带区域检测
3. 关键点头: 锚点+锁扣位置
4. 分类头: 6类状态分类

总参数: ~3M, INT8后 ~800KB
"""

def __init__(self, num_classes=6):
super().__init__()

# 轻量骨干
self.backbone = MobileNetV3Small(in_channels=3)

# 安全带区域检测头
self.belt_det = nn.Sequential(
nn.Conv2d(128, 64, 1),
nn.ReLU(),
nn.Conv2d(64, 2, 1) # 2 anchors
)

# 关键点检测头 (肩部锚点, 锁扣位置, 腰带位置)
self.keypoints = nn.Sequential(
nn.Conv2d(128, 64, 1),
nn.ReLU(),
nn.Conv2d(64, 6, 1) # 3个关键点 × 2(x,y)
)

# 分类头
self.classifier = nn.Sequential(
nn.AdaptiveAvgPool2d(1),
nn.Flatten(),
nn.Linear(128, 64),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(64, num_classes)
)

def forward(self, x):
features = self.backbone(x)
belt_boxes = self.belt_det(features)
belt_keypoints = self.keypoints(features)
logits = self.classifier(features)
return logits, belt_boxes, belt_keypoints


class MobileNetV3Small(nn.Module):
"""轻量骨干网络"""
def __init__(self, in_channels=3):
super().__init__()
self.features = nn.Sequential(
nn.Conv2d(in_channels, 16, 3, 2, 1, bias=False),
nn.BatchNorm2d(16),
nn.Hardswish(inplace=True),
# 简化的MobileNetV3块
nn.Conv2d(16, 32, 3, 2, 1, groups=1, bias=False),
nn.BatchNorm2d(32),
nn.ReLU6(inplace=True),
nn.Conv2d(32, 64, 3, 2, 1, groups=1, bias=False),
nn.BatchNorm2d(64),
nn.ReLU6(inplace=True),
nn.Conv2d(64, 128, 3, 2, 1, bias=False),
nn.BatchNorm2d(128),
nn.Hardswish(inplace=True),
)

def forward(self, x):
return self.features(x)


# ============================================
# 误用判断逻辑
# ============================================

class SeatbeltMisuseClassifier:
"""
基于关键点几何关系判断安全带误用

关键点定义:
- kp0: 肩带锚点 (B柱上方)
- kp1: 锁扣位置
- kp2: 腰带位置 (骨盆附近)
"""

def classify(self, keypoints, person_pose):
"""
Args:
keypoints: (3, 2) 三个关键点坐标
person_pose: dict with shoulders, hips, chest
Returns:
category: str, confidence: float
"""
anchor, buckle, lap = keypoints

# 1. 未系: 无安全带特征
if self._belt_not_visible(keypoints):
return 'unbelted', 0.95

# 2. 正常佩戴: 肩带从锚点→跨胸前→锁扣
if self._normal_pattern(keypoints, person_pose):
return 'normal', 0.90

# 3. 身后佩戴: 肩带方向背离胸前
if self._behind_back_pattern(keypoints, person_pose):
return 'behind_back', 0.75

# 4. 腋下佩戴: 肩带在腋下而非肩上
if self._underarm_pattern(keypoints, person_pose):
return 'underarm', 0.70

# 5. 未锁扣: 安全带拉出但扣环未闭合
if self._unbuckled_pattern(keypoints):
return 'unbuckled', 0.65

return 'uncertain', 0.3

def _belt_not_visible(self, kps):
"""安全带不可见"""
return all(k[0] < 0 for k in kps)

def _normal_pattern(self, kps, pose):
"""正常佩戴: 锚点→胸前→锁扣"""
anchor, buckle, lap = kps
chest = pose.get('chest', (0.5, 0.4))
return (anchor[1] < chest[1] < buckle[1] and # 锚点在上
abs(anchor[0] - buckle[0]) < 0.3) # 水平距离合理

def _behind_back_pattern(self, kps, pose):
"""身后佩戴"""
anchor, buckle, lap = kps
# 肩带方向异常: 不经过胸前
return anchor[1] < buckle[1] and abs(anchor[0] - buckle[0]) > 0.4

def _underarm_pattern(self, kps, pose):
"""腋下佩戴"""
anchor, buckle, lap = kps
armpit = pose.get('right_armpit', (0.6, 0.5))
# 肩带经过腋下而非肩上
return abs(anchor[0] - armpit[0]) < 0.1

def _unbuckled_pattern(self, kps):
"""未锁扣"""
anchor, buckle, lap = kps
# 锁扣位置特征异常
return buckle[0] < 0 or buckle[1] < 0

2. Euro NCAP 安全带场景对应

NCAP场景 描述 视觉检测方案
SB-01 驾驶员正常佩戴 ✅ 分类=normal
SB-02 驾驶员未系 ✅ 分类=unbelted + 锁扣传感器
SB-03 乘员正常佩戴 ✅ 分类=normal
SB-04 乘员未系 ✅ 分类=unbelted + 锁扣传感器
SB-05 安全带身后佩戴 ⚠️ 分类=behind_back
SB-06 安全带腋下佩戴 ⚠️ 分类=underarm
SB-07 安全带未锁扣 ⚠️ 分类=unbuckled

IMS 开发启示

1. 传感器融合策略

传感器 检测范围 可靠性 成本
锁扣传感器 系/未系 100% $2
DMS摄像头 驾驶员安全带 85% 已有
OMS摄像头 乘员安全带 80% $5-10
ToF深度 3D位置 90% $15-25

建议: 锁扣传感器(确定) + 视觉(误用) 融合方案

2. 部署优先级

优先级 任务 目标
P0 锁扣传感器 + 基本视觉检测 系/未系 100%可靠
P1 误用分类模型 身后/腋下/未锁扣
P2 多乘员覆盖 4座全覆盖
P2 与OOP融合 异常姿态+安全带联合判断

3. 数据需求

数据类型 来源 数量 用途
正常佩戴 真实采集 5,000 正例
未系 真实采集 2,000 负例
身后佩戴 合成数据 3,000 误用
腋下佩戴 合成数据 3,000 误用
未锁扣 真实+合成 2,000 误用
遮挡场景 合成数据 2,000 鲁棒性

总结

安全带误用检测从”系/未系”二分类进化到六分类,视觉方案是唯一能检测误用模式的技术路线。建议锁扣传感器(确定性) + 视觉(误用分类)融合方案,用合成数据补充误用样本。


Euro NCAP 2026 OMS协议 | 安全带误用检测技术路线