红外安全带织带:基于摄像头的乘员检测与安全带误用检测

红外安全带织带:基于摄像头的乘员检测与安全带误用检测

新闻来源: Auto-Innovations International
发布时间: 2026年7月24日(3天前)
链接: https://www.auto-innovations.net/news/113135-infrared-seat-belt-webbing-for-camera-based-occupant-detection


核心技术

红外安全带织带(Infrared Seat Belt Webbing),一种无需电子元件的被动式安全带检测方案,通过特殊织带材料使安全带在红外摄像头下清晰可见,实现乘员检测和安全带误用检测。

技术突破:

  1. 无需在安全带中集成电子元件
  2. 红外摄像头可直接识别安全带位置
  3. 支持所有座位的安全带状态检测
  4. 2026年8月量产,可直接集成到现有生产流程

技术原理

1. 传统方案 vs 红外织带方案

方案 检测原理 优点 缺点
传统安全带传感器 机械开关/电容式 成熟稳定 只检测是否插入,无法检测佩戴位置
智能安全带 嵌入式传感器 可检测张力、位置 成本高、需要电源、安装复杂
红外织带 红外反射材料 无电子元件、摄像头直接识别 需要红外摄像头

2. 工作原理

graph TB
    A[红外补光LED] --> B[红外织带反射]
    B --> C[红外摄像头捕获]
    
    C --> D[安全带位置检测]
    D --> E[佩戴状态判定]
    
    E --> F{是否正确佩戴?}
    F -->|是| G[安全系统就绪]
    F -->|否| H[发出警告+调整气囊策略]

3. 检测的安全带状态

状态 描述 风险等级
正确佩戴 安全带跨肩、贴胸、扣紧 ✅ 正常
未佩戴 安全带未扣紧 🔴 高风险
斜跨错误 安全带斜跨错误(如从颈部下方穿过) 🟡 中风险
背后佩戴 安全带从背后穿过 🔴 高风险
过松 安全带张力不足 🟡 中风险

核心算法实现

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
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
import cv2
import numpy as np
from typing import List, Dict, Tuple
from dataclasses import dataclass
from enum import Enum

class BeltStatus(Enum):
"""安全带状态枚举"""
CORRECTLY_WORN = 0 # 正确佩戴
NOT_WORN = 1 # 未佩戴
IMPROPER_POSITION = 2 # 位置错误
BEHIND_BACK = 3 # 背后佩戴
TOO_LOOSE = 4 # 过松

@dataclass
class BeltDetection:
"""安全带检测结果"""
status: BeltStatus
confidence: float
belt_points: List[Tuple[int, int]] # 安全带关键点
shoulder_position: str # 肩部位置描述

class InfraredBeltDetector:
"""红外安全带检测器"""

def __init__(self):
# 红外阈值(针对特殊织带材料)
self.ir_threshold = 200 # 高反射强度

# 安全带关键点检测器(基于深度学习)
# self.belt_keypoint_model = self._load_model()

# 人体关键点(用于判断安全带位置)
self.body_keypoints = {
'left_shoulder': (0, 0),
'right_shoulder': (0, 0),
'chest_center': (0, 0),
'left_hip': (0, 0),
'right_hip': (0, 0)
}

def detect(self, ir_image: np.ndarray, body_keypoints: Dict) -> BeltDetection:
"""
检测安全带状态

Args:
ir_image: 红外图像 (H, W)
body_keypoints: 人体关键点

Returns:
detection: 安全带检测结果
"""
self.body_keypoints = body_keypoints

# 1. 红外图像预处理
ir_enhanced = self._enhance_ir_image(ir_image)

# 2. 检测高亮安全带区域
belt_mask = self._detect_belt_region(ir_enhanced)

# 3. 提取安全带骨架
belt_skeleton = self._extract_skeleton(belt_mask)

# 4. 拟合安全带曲线
belt_points = self._fit_belt_curve(belt_skeleton)

# 5. 判定佩戴状态
status, confidence = self._classify_belt_status(belt_points)

return BeltDetection(
status=status,
confidence=confidence,
belt_points=belt_points,
shoulder_position=self._describe_shoulder_position(belt_points)
)

def _enhance_ir_image(self, ir_image: np.ndarray) -> np.ndarray:
"""增强红外图像"""
# 直方图均衡化
ir_enhanced = cv2.equalizeHist(ir_image)

# 去噪
ir_enhanced = cv2.GaussianBlur(ir_enhanced, (5, 5), 0)

return ir_enhanced

def _detect_belt_region(self, ir_image: np.ndarray) -> np.ndarray:
"""检测安全带区域"""
# 阈值分割(红外织带高反射)
_, belt_mask = cv2.threshold(ir_image, self.ir_threshold, 255, cv2.THRESH_BINARY)

# 形态学处理
kernel = np.ones((5, 5), np.uint8)
belt_mask = cv2.morphologyEx(belt_mask, cv2.MORPH_CLOSE, kernel)
belt_mask = cv2.morphologyEx(belt_mask, cv2.MORPH_OPEN, kernel)

# 连通域分析
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(belt_mask)

# 过滤小区域(噪声)
min_area = 500 # 最小面积
valid_mask = np.zeros_like(belt_mask)

for i in range(1, num_labels):
if stats[i, cv2.CC_STAT_AREA] > min_area:
valid_mask[labels == i] = 255

return valid_mask

def _extract_skeleton(self, mask: np.ndarray) -> np.ndarray:
"""提取骨架"""
skeleton = np.zeros_like(mask, dtype=np.uint8)

# 迭代腐蚀
kernel = np.ones((3, 3), np.uint8)
temp = mask.copy()

while cv2.countNonZero(temp) > 0:
eroded = cv2.erode(temp, kernel)
skeleton_part = cv2.subtract(temp, cv2.dilate(eroded, kernel))
skeleton = cv2.bitwise_or(skeleton, skeleton_part)
temp = eroded

return skeleton

def _fit_belt_curve(self, skeleton: np.ndarray) -> List[Tuple[int, int]]:
"""拟合安全带曲线"""
# 提取骨架点
points = np.column_stack(np.where(skeleton > 0))

if len(points) < 10:
return []

# 按y坐标排序
points = points[np.argsort(points[:, 0])]

# 简化:均匀采样
num_points = 20
indices = np.linspace(0, len(points)-1, num_points).astype(int)
sampled_points = points[indices]

# 转换为(x, y)格式
belt_points = [(int(p[1]), int(p[0])) for p in sampled_points]

return belt_points

def _classify_belt_status(self, belt_points: List[Tuple[int, int]]) -> Tuple[BeltStatus, float]:
"""分类安全带状态"""
if len(belt_points) < 5:
return BeltStatus.NOT_WORN, 0.95

# 提取关键点
left_shoulder = self.body_keypoints['left_shoulder']
right_shoulder = self.body_keypoints['right_shoulder']
chest_center = self.body_keypoints['chest_center']

# 计算安全带起点和终点
belt_start = belt_points[0] # 肩部起点
belt_end = belt_points[-1] # 腰部终点

# 检查安全带是否跨过肩膀
belt_crosses_shoulder = self._check_shoulder_crossing(belt_points, left_shoulder, right_shoulder)

# 检查安全带是否靠近胸部中心
belt_near_chest = self._check_chest_proximity(belt_points, chest_center)

# 综合判定
if belt_crosses_shoulder and belt_near_chest:
return BeltStatus.CORRECTLY_WORN, 0.85
elif not belt_crosses_shoulder:
return BeltStatus.IMPROPER_POSITION, 0.75
elif not belt_near_chest:
return BeltStatus.BEHIND_BACK, 0.70
else:
return BeltStatus.TOO_LOOSE, 0.60

def _check_shoulder_crossing(self, belt_points: List[Tuple[int, int]],
left_shoulder: Tuple[int, int],
right_shoulder: Tuple[int, int]) -> bool:
"""检查安全带是否正确跨过肩膀"""
# 简化:检查安全带起点是否在肩膀附近
belt_start = belt_points[0]

# 计算与肩膀的距离
dist_left = np.sqrt((belt_start[0] - left_shoulder[0])**2 +
(belt_start[1] - left_shoulder[1])**2)
dist_right = np.sqrt((belt_start[0] - right_shoulder[0])**2 +
(belt_start[1] - right_shoulder[1])**2)

# 任一肩膀距离<50像素视为正确
return dist_left < 50 or dist_right < 50

def _check_chest_proximity(self, belt_points: List[Tuple[int, int]],
chest_center: Tuple[int, int]) -> bool:
"""检查安全带是否靠近胸部"""
# 取安全带中点
mid_idx = len(belt_points) // 2
belt_mid = belt_points[mid_idx]

# 计算与胸部中心的距离
dist = np.sqrt((belt_mid[0] - chest_center[0])**2 +
(belt_mid[1] - chest_center[1])**2)

# 距离<100像素视为正确
return dist < 100

def _describe_shoulder_position(self, belt_points: List[Tuple[int, int]]) -> str:
"""描述安全带肩部位置"""
if len(belt_points) < 2:
return "未检测到安全带"

# 简化描述
return "安全带从左肩跨过"


# 完整系统集成测试
if __name__ == "__main__":
# 初始化
detector = InfraredBeltDetector()

# 模拟红外图像(高亮部分为安全带)
ir_image = np.zeros((480, 640), dtype=np.uint8)

# 绘制安全带(从左上到右下的斜线)
cv2.line(ir_image, (150, 100), (450, 400), 255, 10)

# 模拟人体关键点
body_keypoints = {
'left_shoulder': (200, 150),
'right_shoulder': (400, 150),
'chest_center': (300, 250),
'left_hip': (250, 400),
'right_hip': (350, 400)
}

# 检测
result = detector.detect(ir_image, body_keypoints)

print(f"安全带状态: {result.status.name}")
print(f"置信度: {result.confidence:.2f}")
print(f"肩部位置: {result.shoulder_position}")
print(f"检测到的关键点数: {len(result.belt_points)}")

2. 多座位检测系统

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
class MultiSeatBeltMonitor:
"""多座位安全带监测系统"""

def __init__(self):
self.detector = InfraredBeltDetector()

# 座位配置
self.seats = {
'driver': {'roi': (100, 50, 400, 450), 'body_keypoints': {}},
'passenger': {'roi': (400, 50, 640, 450), 'body_keypoints': {}},
'rear_left': {'roi': (50, 200, 250, 450), 'body_keypoints': {}},
'rear_right': {'roi': (350, 200, 550, 450), 'body_keypoints': {}}
}

def monitor_all_seats(self, ir_image: np.ndarray, body_keypoints_all: Dict) -> Dict:
"""
监测所有座位的安全带状态

Args:
ir_image: 全车红外图像
body_keypoints_all: 所有座位的人体关键点

Returns:
seat_results: 各座位检测结果
"""
seat_results = {}

for seat_name, seat_config in self.seats.items():
# 提取ROI
x1, y1, x2, y2 = seat_config['roi']
seat_image = ir_image[y1:y2, x1:x2]

# 获取该座位的人体关键点
body_keypoints = body_keypoints_all.get(seat_name, {})

if body_keypoints:
# 检测安全带
result = self.detector.detect(seat_image, body_keypoints)
seat_results[seat_name] = {
'status': result.status.name,
'confidence': result.confidence,
'belt_points': result.belt_points
}
else:
seat_results[seat_name] = {
'status': 'NO_OCCUPANT',
'confidence': 1.0,
'belt_points': []
}

return seat_results

def generate_warning(self, seat_results: Dict) -> List[Dict]:
"""生成警告信息"""
warnings = []

for seat_name, result in seat_results.items():
status = result['status']

if status == 'NOT_WORN':
warnings.append({
'seat': seat_name,
'severity': 'high',
'message': f'{seat_name}座位未佩戴安全带',
'action': '发出声音警告+仪表盘提示'
})
elif status == 'IMPROPER_POSITION':
warnings.append({
'seat': seat_name,
'severity': 'medium',
'message': f'{seat_name}座位安全带位置不正确',
'action': '发出声音警告+调整气囊策略'
})
elif status == 'BEHIND_BACK':
warnings.append({
'seat': seat_name,
'severity': 'high',
'message': f'{seat_name}座位安全带从背后穿过',
'action': '发出警告+禁用气囊'
})

return warnings


# 测试多座位监测
if __name__ == "__main__":
monitor = MultiSeatBeltMonitor()

# 模拟全车红外图像
full_ir_image = np.zeros((480, 640), dtype=np.uint8)

# 模拟驾驶员安全带
cv2.line(full_ir_image, (150, 100), (350, 400), 255, 10)

# 模拟人体关键点
body_keypoints_all = {
'driver': {
'left_shoulder': (200, 150),
'right_shoulder': (350, 150),
'chest_center': (280, 250),
'left_hip': (220, 400),
'right_hip': (320, 400)
},
'passenger': {} # 无乘客
}

# 监测
results = monitor.monitor_all_seats(full_ir_image, body_keypoints_all)

print("\n各座位安全带状态:")
for seat, result in results.items():
print(f"{seat}: {result['status']} (置信度: {result['confidence']:.2f})")

# 生成警告
warnings = monitor.generate_warning(results)
if warnings:
print("\n警告信息:")
for warning in warnings:
print(f" [{warning['severity']}] {warning['message']}")
print(f" 建议动作: {warning['action']}")

与Euro NCAP 2026对接

安全带误用检测场景

场景编号 场景描述 检测要求
BM-01 未佩戴安全带 ≤3秒检测并发出一级警告
BM-02 安全带位置错误(斜跨不当) ≤5秒检测并发出警告
BM-03 安全带从背后穿过 ≤3秒检测并调整气囊策略
BM-04 安全带过松 ≤5秒检测并发出提示
BM-05 儿童座椅安全带状态 检测并提示

气囊联动策略

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
class AirbagController:
"""气囊控制器(与安全带检测联动)"""

def __init__(self):
# 气囊配置
self.airbags = {
'driver_front': {'enabled': True, 'power': 100},
'passenger_front': {'enabled': True, 'power': 100},
'side': {'enabled': True, 'power': 80},
'curtain': {'enabled': True, 'power': 80}
}

def adjust_for_belt_status(self, belt_status: BeltStatus):
"""根据安全带状态调整气囊策略"""
if belt_status == BeltStatus.CORRECTLY_WORN:
# 正常配置
pass

elif belt_status == BeltStatus.NOT_WORN:
# 未佩戴:增加气囊敏感度
self.airbags['driver_front']['power'] = 120
self._log_event('AIRBAG_ADJUSTED', 'Increased power due to no seatbelt')

elif belt_status == BeltStatus.BEHIND_BACK:
# 背后佩戴:禁用前排气囊(防止伤害)
self.airbags['driver_front']['enabled'] = False
self._log_event('AIRBAG_DISABLED', 'Front airbag disabled due to improper belt position')

elif belt_status == BeltStatus.IMPROPER_POSITION:
# 位置错误:降低气囊功率
self.airbags['driver_front']['power'] = 80
self._log_event('AIRBAG_ADJUSTED', 'Reduced power due to improper belt position')

def _log_event(self, event_type: str, message: str):
"""记录事件"""
print(f"[AIRBAG] {event_type}: {message}")


# 测试气囊联动
if __name__ == "__main__":
airbag_ctrl = AirbagController()

# 模拟安全带状态
test_cases = [
(BeltStatus.CORRECTLY_WORN, "正确佩戴"),
(BeltStatus.NOT_WORN, "未佩戴"),
(BeltStatus.BEHIND_BACK, "背后佩戴"),
(BeltStatus.IMPROPER_POSITION, "位置错误")
]

print("\n气囊联动测试:")
for status, desc in test_cases:
print(f"\n安全带状态: {desc}")
airbag_ctrl.adjust_for_belt_status(status)
print(f"当前气囊配置: {airbag_ctrl.airbags}")

IMS开发启示

1. 硬件集成方案

组件 型号 功能 成本
红外摄像头 OV2311 RGB-IR 安全带检测+DMS $15
红外LED SFH 4740 940nm补光 $2
红外织带 特殊材料安全带 被动反射 $5/米

总成本:约$22/座位(比传统智能安全带降低50%)

2. 软件优化方向

优化项 方法 效果
实时检测 边缘AI推理 帧率>30fps
遮挡处理 多视角融合 遮挡时仍可检测
低光照 红外补光自适应 夜间精度不降

3. 与现有DMS系统融合

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
class IntegratedDMSBeltSystem:
"""DMS与安全带检测融合系统"""

def __init__(self):
self.dms = DMSModule() # 驾驶员监测
self.belt_detector = InfraredBeltDetector()

self.status = {
'dms': None,
'belt': None
}

def process_frame(self, frame: np.ndarray):
"""处理单帧"""
# 1. DMS检测
dms_result = self.dms.detect(frame)

# 2. 安全带检测
belt_result = self.belt_detector.detect(frame, dms_result['body_keypoints'])

# 3. 融合分析
combined_status = self._analyze_combined_status(dms_result, belt_result)

return combined_status

def _analyze_combined_status(self, dms_result, belt_result):
"""综合分析"""
# 如果未佩戴安全带,增加DMS敏感度
if belt_result.status == BeltStatus.NOT_WORN:
dms_sensitivity = 'high'
else:
dms_sensitivity = 'normal'

return {
'dms_status': dms_result,
'belt_status': belt_result,
'dms_sensitivity': dms_sensitivity
}


class DMSModule:
"""DMS模块(简化)"""

def detect(self, frame):
return {
'body_keypoints': {
'left_shoulder': (200, 150),
'right_shoulder': (350, 150),
'chest_center': (280, 250)
},
'fatigue_level': 0.2,
'distraction_level': 0.1
}

4. 开发路线图

阶段 时间 目标
Phase 1 2周 红外图像安全带检测算法
Phase 2 1周 多座位系统集成
Phase 3 2周 气囊控制器联动
Phase 4 1周 Euro NCAP场景测试

量产时间表

时间节点 进展
2026年8月 量产开始
2026年Q4 首款车型搭载
2027年 扩展到所有座位

参考文献

  1. Auto-Innovations, “Infrared Seat Belt Webbing for Camera-Based Occupant Detection”, 2026
  2. Euro NCAP, “Seat Belt Misuse Detection Requirements”, 2026
  3. TI, “AWRL6432 60GHz Radar for CPD”, 2026

本文为红外安全带织带方案的详细解读与代码实现,面向Euro NCAP 2026安全带误用检测要求,提供可直接落地的被动式安全带检测方案。


红外安全带织带:基于摄像头的乘员检测与安全带误用检测
https://dapalm.com/2026/07/27/2026-07-27-infrared-seatbelt-webbing-occupant-detection/
作者
Mars
发布于
2026年7月27日
许可协议