安全带错误佩戴检测:从视觉识别到Euro NCAP合规

安全带错误佩戴检测:从视觉识别到 Euro NCAP 合规


背景:Euro NCAP 2026 新规

安全带检测升级

Euro NCAP 2026 协议明确要求:

“The system should recognize if a seatbelt is buckled but not worn correctly – for example, behind the back or only across the lap.”

—— Smart Eye, Euro NCAP 2026 解读

核心变化:

旧版要求 2026 新要求
检测安全带是否系上 检测安全带是否正确佩戴
仅前排检测 前排 + 后排全覆盖
简单开关信号 视觉 + 传感器融合
2-3 分 5 分(满分提升)

错误佩戴场景

Euro NCAP 定义的错误佩戴类型:

类型 描述 风险等级
背后佩戴 安全带绕过肩部,从背后穿过 极高
仅腰部 肩带未被使用,仅系腰带
腋下佩戴 肩带从腋下穿过
扭曲佩戴 安全带扭曲,受力不均
过松 安全带松弛,无法有效约束
儿童错误使用 儿童使用成人安全带 极高

1. 技术方案对比

1.1 传感器方案

方案 原理 优点 缺点 Euro NCAP 适用性
摄像头 视觉识别安全带位置 ✅ 可检测佩戴方式 ⚠️ 受光照影响 ✅ 最佳方案
压力传感器 检测肩部压力 ✅ 简单可靠 ❌ 无法区分佩戴方式 ⚠️ 辅助
** buckle 传感器** 检测锁扣状态 ✅ 成熟可靠 ❌ 无法检测错误佩戴 ⚠️ 基础需求
超声波 检测距离 ✅ 不受光照影响 ❌ 精度有限 ⚠️ 辅助

最佳方案:摄像头 + 压力传感器融合

“Neonode’s seatbelt detection allows OEMs to gain maximum points in the Euro NCAP safety rating for seatbelt misuse. Unlike traditional systems, Neonode’s camera-based system can identify seatbelt misuse and ensure proper seatbelt routing.”

—— Neonode, 2026

1.2 Neonode 方案详解

Neonode 官方说明:

“The 2026 Euro NCAP protocols include seatbelt routing as part of the Safe Driving Seatbelt Usage criteria, awarding up to 5 points for detecting whether the driver’s seatbelt is worn correctly rather than merely buckled.”

技术特点:

  • 基于摄像头的视觉检测
  • AI 算法识别安全带路径
  • 可区分正确佩戴 vs 错误佩戴

2. 视觉检测算法

2.1 安全带分割

算法流程:

  1. 图像预处理 → 增强对比度
  2. 安全带分割 → 提取安全带区域
  3. 路径追踪 → 分析安全带走向
  4. 佩戴判断 → 分类为正确/错误

代码实现:

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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
import cv2
import numpy as np
from typing import Tuple, List, Optional
from dataclasses import dataclass

@dataclass
class SeatbeltResult:
"""安全带检测结果"""
is_buckled: bool
is_correctly_worn: bool
misuse_type: Optional[str] # None, "behind_back", "under_arm", "lap_only"
confidence: float
belt_path: List[Tuple[int, int]] # 安全带路径点

class SeatbeltMisuseDetector:
"""
安全带错误佩戴检测器

基于视觉识别判断安全带是否正确佩戴
"""

def __init__(self):
# 安全带颜色范围(假设为黑色/深灰色)
self.belt_color_lower = np.array([0, 0, 0])
self.belt_color_upper = np.array([180, 255, 80])

# 人体关键区域定义
self.shoulder_region = (0.3, 0.5, 0.7, 0.9) # (x1, y1, x2, y2) 归一化坐标
self.chest_region = (0.3, 0.5, 0.7, 0.7)
self.lap_region = (0.3, 0.7, 0.7, 0.95)

def segment_seatbelt(self, image: np.ndarray) -> np.ndarray:
"""
分割安全带区域

Args:
image: BGR 图像

Returns:
mask: 安全带二值掩码
"""
# 转换到 HSV 空间
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

# 颜色分割
mask = cv2.inRange(hsv, self.belt_color_lower, self.belt_color_upper)

# 形态学处理
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)

return mask

def extract_belt_path(self, mask: np.ndarray) -> List[Tuple[int, int]]:
"""
提取安全带路径

Args:
mask: 安全带二值掩码

Returns:
path: 安全带中心线路径点列表
"""
# 查找轮廓
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

if not contours:
return []

# 取最大轮廓
largest_contour = max(contours, key=cv2.contourArea)

# 提取中心线
# 使用骨架化算法
skeleton = self._skeletonize(mask)

# 提取路径点
points = np.where(skeleton > 0)
path = list(zip(points[1], points[0])) # (x, y)

# 排序路径点(从上到下)
path.sort(key=lambda p: p[1])

return path

def _skeletonize(self, mask: np.ndarray) -> np.ndarray:
"""骨架化"""
skeleton = np.zeros(mask.shape, np.uint8)
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))

while True:
eroded = cv2.erode(mask, element)
temp = cv2.dilate(eroded, element)
temp = cv2.subtract(mask, temp)
skeleton = cv2.bitwise_or(skeleton, temp)
mask = eroded.copy()

if cv2.countNonZero(mask) == 0:
break

return skeleton

def classify_wearing_type(
self,
belt_path: List[Tuple[int, int]],
image_shape: Tuple[int, int]
) -> Tuple[bool, Optional[str]]:
"""
分类佩戴类型

Args:
belt_path: 安全带路径点
image_shape: 图像尺寸 (H, W)

Returns:
(is_correct, misuse_type): 是否正确佩戴,错误类型
"""
if len(belt_path) < 10:
return False, "no_belt"

h, w = image_shape[:2]

# 归一化路径
normalized_path = [(x / w, y / h) for x, y in belt_path]

# 分析路径走向
# 正确佩戴:从肩部斜向下经过胸部到腰部

# 检查 1:安全带是否经过肩部区域
shoulder_points = [
p for p in normalized_path
if self.shoulder_region[0] <= p[0] <= self.shoulder_region[2]
and self.shoulder_region[1] <= p[1] <= self.shoulder_region[3]
]

# 检查 2:安全带是否经过胸部区域
chest_points = [
p for p in normalized_path
if self.chest_region[0] <= p[0] <= self.chest_region[2]
and self.chest_region[1] <= p[1] <= self.chest_region[3]
]

# 检查 3:安全带是否经过腰部区域
lap_points = [
p for p in normalized_path
if self.lap_region[0] <= p[0] <= self.lap_region[2]
and self.lap_region[1] <= p[1] <= self.lap_region[3]
]

# 判断逻辑
has_shoulder = len(shoulder_points) > 3
has_chest = len(chest_points) > 5
has_lap = len(lap_points) > 3

if has_shoulder and has_chest and has_lap:
# 路径完整,检查斜率
if len(belt_path) > 20:
# 计算整体斜率
top_points = belt_path[:10]
bottom_points = belt_path[-10:]

top_center = np.mean(top_points, axis=0)
bottom_center = np.mean(bottom_points, axis=0)

slope = (bottom_center[1] - top_center[1]) / (bottom_center[0] - top_center[0] + 1e-6)

# 正确斜率:从肩部向对侧腰部
if slope > 0.5: # 合理斜率
return True, None

# 错误佩戴判断
if has_lap and not has_shoulder:
return False, "lap_only"

if has_shoulder and not has_chest:
return False, "behind_back"

if has_shoulder and has_chest:
# 检查是否从腋下穿过
# 如果路径过于靠近身体中线
chest_x_mean = np.mean([p[0] for p in chest_points])
if chest_x_mean < 0.4: # 偏离肩部
return False, "under_arm"

return False, "unknown"

def detect(self, image: np.ndarray) -> SeatbeltResult:
"""
完整检测流程

Args:
image: BGR 图像

Returns:
result: 检测结果
"""
# 1. 分割安全带
mask = self.segment_seatbelt(image)

# 2. 提取路径
belt_path = self.extract_belt_path(mask)

# 3. 判断是否系上
is_buckled = len(belt_path) > 10

# 4. 判断佩戴类型
if is_buckled:
is_correct, misuse_type = self.classify_wearing_type(belt_path, image.shape)
else:
is_correct = False
misuse_type = "no_belt"

# 5. 计算置信度
confidence = min(1.0, len(belt_path) / 50.0)

return SeatbeltResult(
is_buckled=is_buckled,
is_correctly_worn=is_correct,
misuse_type=misuse_type,
confidence=confidence,
belt_path=belt_path
)


# 实际测试
if __name__ == "__main__":
# 创建检测器
detector = SeatbeltMisuseDetector()

# 模拟测试
# 创建模拟图像:正确佩戴
correct_image = np.zeros((480, 640, 3), dtype=np.uint8)
# 画一条从右上到左下的斜线(模拟安全带)
cv2.line(correct_image, (450, 100), (200, 400), (50, 50, 50), 10)

result = detector.detect(correct_image)
print(f"正确佩戴检测: 系上={result.is_buckled}, 正确={result.is_correctly_worn}, 类型={result.misuse_type}")

# 创建模拟图像:仅腰部
lap_only_image = np.zeros((480, 640, 3), dtype=np.uint8)
cv2.line(lap_only_image, (400, 350), (240, 380), (50, 50, 50), 10)

result2 = detector.detect(lap_only_image)
print(f"仅腰部检测: 系上={result2.is_buckled}, 正确={result2.is_correctly_worn}, 类型={result2.misuse_type}")

3. Euro NCAP 2026 测试场景

3.1 官方测试用例

场景 ID 描述 检测要求 通过条件
SB-01 驾驶员正确佩戴安全带 识别正确佩戴 无警告
SB-02 驾驶员未系安全带 检测未系状态 ≤3秒警告
SB-03 安全带背后佩戴 识别错误佩戴 ≤5秒警告
SB-04 安全带仅腰部 识别错误佩戴 ≤5秒警告
SB-05 安全带腋下佩戴 识别错误佩戴 ≤5秒警告
SB-06 后排乘客未系 检测后排状态 ≤10秒警告
SB-07 儿童座椅安全带 特殊处理 根据场景

3.2 得分机制

Euro NCAP 2026 安全带检测得分:

功能 分值 说明
前排未系检测 1 分 基础要求
后排未系检测 1 分 2026 新增
错误佩戴检测 3 分 2026 新增核心
总分 5 分 满分

4. 多传感器融合方案

4.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
class SeatbeltFusionDetector:
"""
安全带检测融合系统

融合摄像头 + 压力传感器 + buckle 传感器
"""

def __init__(self):
self.vision_detector = SeatbeltMisuseDetector()
self.pressure_threshold = 0.5 # kg

def detect(
self,
image: np.ndarray,
buckle_state: bool,
shoulder_pressure: float,
lap_pressure: float
) -> SeatbeltResult:
"""
融合检测

Args:
image: 摄像头图像
buckle_state: 锁扣状态(True=已扣)
shoulder_pressure: 肩部压力(kg)
lap_pressure: 腰部压力(kg)

Returns:
result: 融合检测结果
"""
# 1. 视觉检测
vision_result = self.vision_detector.detect(image)

# 2. 压力传感器检测
has_shoulder_pressure = shoulder_pressure > self.pressure_threshold
has_lap_pressure = lap_pressure > self.pressure_threshold

# 3. 融合判断
if not buckle_state:
# 锁扣未扣
return SeatbeltResult(
is_buckled=False,
is_correctly_worn=False,
misuse_type="not_buckled",
confidence=1.0,
belt_path=[]
)

# 锁扣已扣,但需要判断是否正确佩戴
if vision_result.is_correctly_worn and has_shoulder_pressure and has_lap_pressure:
# 视觉 + 压力都确认正确
return SeatbeltResult(
is_buckled=True,
is_correctly_worn=True,
misuse_type=None,
confidence=0.95,
belt_path=vision_result.belt_path
)

if vision_result.misuse_type == "lap_only" and not has_shoulder_pressure:
# 视觉检测仅腰部 + 肩部无压力 = 确认
return SeatbeltResult(
is_buckled=True,
is_correctly_worn=False,
misuse_type="lap_only",
confidence=0.9,
belt_path=vision_result.belt_path
)

if vision_result.misuse_type == "behind_back" and has_shoulder_pressure:
# 视觉检测背后佩戴 + 但肩部有压力 = 可能误判
# 保守判断:警告
return SeatbeltResult(
is_buckled=True,
is_correctly_worn=False,
misuse_type="behind_back",
confidence=0.7,
belt_path=vision_result.belt_path
)

# 默认返回视觉结果
return vision_result

4.2 传感器配置

推荐配置:

传感器 位置 数量 用途
IR 摄像头 A 柱 / 车顶 1-2 视觉检测
压力传感器 座椅肩部 2 辅助判断
buckle 传感器 锁扣 1 基础检测

5. IMS 开发建议

5.1 功能优先级

优先级 功能 开发周期 Euro NCAP 得分
P0 前排未系检测 1 周 1 分
P0 视觉分割算法 2 周 -
P1 错误佩戴分类 2 周 3 分
P1 后排检测 2 周 1 分
P2 多传感器融合 3 周 提升鲁棒性

5.2 硬件成本

方案 传感器成本 总成本
仅 buckle 传感器 $5 $5
+ 摄像头 $30 $35
+ 压力传感器 $10 $45

6. 参考资料

官方文档

  1. Euro NCAP 2026 Seatbelt Requirements - Smart Eye
    链接:https://smarteye.se/blog/euro-ncap-2026-seatbelt-use/

  2. Euro NCAP 2026: What’s Changing - Smart Eye
    链接:https://smarteye.se/blog/euro-ncap-2026-whats-changing/

企业方案

  1. Neonode Seatbelt Detection
    链接:https://neonode.com/solutions/in-cabin-sensing/seatbelt-detection

  2. Sky Engine AI: Synthetic Data for Euro NCAP 2026
    链接:https://www.skyengine.ai/blog/navigating-euro-ncap-2026-how-synthetic-data-powers-next-gen-in-cabin-monitoring-systems


本文由 OpenClaw 研究系统自动生成,基于 Euro NCAP 2026 官方协议与行业最新动态。


安全带错误佩戴检测:从视觉识别到Euro NCAP合规
https://dapalm.com/2026/05/31/2026-05-31-安全带错误佩戴检测:从视觉识别到Euro-NCAP合规/
作者
Mars
发布于
2026年5月31日
许可协议