多视角车内监测数据集——德国城市巴士的3D姿态与行为标注实践

论文信息

  • 标题: Multi-View In-Cabin Monitoring System for Public Transport Vehicles
  • 作者: Evgeny Gorelik, Kenny Dean Karrow, Fikret Sivrikaya, Sahin Albayrak (TU Berlin), Christian Baumann (MAN Truck & Bus SE)
  • 链接: https://arxiv.org/html/2606.11739v1
  • 年份: 2026

核心贡献

本文发布了一个多视角、多模态的车内监测数据集,在德国城市巴士内采集,包含:

  • 4个内向摄像头 同步RGB+深度图像
  • 1个旋转LiDAR (Ouster OS0-128, 128线)
  • 9,136个同步标注样本
  • 3D人体姿态伪标签 + 朝向3D包围盒
  • 动作标注:状态类别 + 行为类别
  • nuScenes格式 转换,支持标准模型训练

数据集规格

指标 数值
同步样本总数 10,034 (有效标注 9,136)
摄像头数量 4 (Intel RealSense D435i)
RGB帧率 15 Hz
LiDAR帧率 10 Hz
LiDAR线数 128 (Ouster OS0-128)
占用人数 1-2人/场景
动作类别 15种
标注类型 2D mask/box, 3D pose, 3D bbox, track

传感器布局

硬件配置

组件 型号 数量 参数
深度相机 Intel RealSense D435i 4 RGB 1280×720, 深度 1280×720, 30fps
LiDAR Ouster OS0-128 1 128线, 10Hz, 0.5°-40° FOV
计算节点 Intel NUC 11 1 i7, 16GB RAM, Ubuntu 22.04
边缘节点 Raspberry Pi 4 4 8GB RAM, PoE供电
网络 PoE Switch 1 1Gbps带宽
软件 ROS 2 + Cyclone DDS — 时间同步NTP

动作标注体系

状态类别(姿态/运动状态)

标签 描述 与IMS关联
sit 坐着 正常驾驶/乘员状态
sit down 坐下动作 检测乘客上车落座
stand up 站起动作 检测乘客起身/离座
stand 站立 异常OOP姿态
walk 行走 车内移动检测
enter vehicle 上车 入口监控
exit vehicle 下车 出口监控
hold on 抓扶手 公交场景特有

行为类别(交互/异常事件)

标签 描述 与IMS关联
drinking non-alcoholic 喝非酒精饮料 分心检测参考
drinking alcoholic 喝酒精饮料 酒驾检测
smoking 吸烟 危险行为检测
defacement 破坏公物 安全事件
vandalism 故意破坏 安全事件
lost item 遗失物品 Robotaxi PMS
mugging 抢劫 安全事件
pushing 推搡 暴力检测
littering 乱扔垃圾 文明监控
punching 打人 暴力检测

标注生成管道

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
import numpy as np
from typing import List, Dict

class PseudoLabelPipeline:
"""
多视角车内标注伪标签生成管道

论文: Gorelik et al., 2026
流程: 2D检测 → 3D姿态估计 → 跨视角追踪 → 3D包围盒提取
"""

def __init__(self, camera_intrinsics: List[dict], extrinsics: List[np.ndarray]):
"""
Args:
camera_intrinsics: 各相机内参列表
extrinsics: 各相机外参列表 (4x4 变换矩阵)
"""
self.num_cameras = len(camera_intrinsics)
self.intrinsics = camera_intrinsics
self.extrinsics = extrinsics

def process_frame(
self,
rgb_images: List[np.ndarray],
depth_images: List[np.ndarray],
lidar_points: np.ndarray
) -> Dict:
"""
处理一帧多视角数据

Args:
rgb_images: 4个相机的RGB图, shape=(4, H, W, 3)
depth_images: 4个相机的深度图, shape=(4, H, W)
lidar_points: LiDAR点云, shape=(N, 3)

Returns:
annotations: 标注结果
"""
results = {}

# Step 1: 2D检测 (每视角独立)
detections_2d = []
for i in range(self.num_cameras):
dets = self._detect_2d(rgb_images[i])
detections_2d.append(dets)

# Step 2: 3D姿态估计 (每视角)
poses_3d = []
for i in range(self.num_cameras):
pose = self._estimate_3d_pose(
rgb_images[i],
depth_images[i],
detections_2d[i]
)
poses_3d.append(pose)

# Step 3: 跨视角追踪关联
tracks = self._cross_view_track(detections_2d, poses_3d)

# Step 4: 3D包围盒提取
boxes_3d = self._extract_3d_bbox(poses_3d, tracks, lidar_points)

results['detections_2d'] = detections_2d
results['poses_3d'] = poses_3d
results['tracks'] = tracks
results['boxes_3d'] = boxes_3d

return results

def _detect_2d(self, rgb: np.ndarray) -> list:
"""2D人员检测 (模拟YOLO)"""
# 实际使用YOLO检测
return [{'bbox': [100, 200, 150, 400], 'score': 0.95}]

def _estimate_3d_pose(self, rgb, depth, detections):
"""单视角3D姿态估计"""
poses = []
for det in detections:
# 提取2D关键点 → 映射深度 → 3D坐标
pose_3d = self._depth_to_3d(depth, det['bbox'])
poses.append(pose_3d)
return poses

def _depth_to_3d(self, depth, bbox):
"""深度图 → 3D坐标"""
h, w = depth.shape
cx, cy = w // 2, h // 2
fx = fy = 615.0 # RealSense D435i

x1, y1, x2, y2 = bbox
center_u = (x1 + x2) // 2
center_v = (y1 + y2) // 2

z = depth[center_v, center_x]
x = (center_u - cx) * z / fx
y = (center_v - cy) * z / fy

return {'center_3d': [x, y, z], 'confidence': 0.9}

def _cross_view_track(self, detections, poses):
"""跨视角追踪关联"""
# 基于IoU和3D距离的关联
tracks = []
for i in range(len(detections)):
for j in range(i+1, len(detections)):
# 简化: 检查3D中心距离
if poses[i] and poses[j]:
dist = np.linalg.norm(
np.array(poses[i][0]['center_3d']) -
np.array(poses[j][0]['center_3d'])
)
if dist < 500: # 500mm内视为同一人
tracks.append({'view_a': i, 'view_b': j, 'dist': dist})
return tracks

def _extract_3d_bbox(self, poses, tracks, lidar):
"""从姿态和LiDAR提取3D包围盒"""
boxes = []
for pose_list in poses:
for pose in pose_list:
center = pose['center_3d']
# 默认人体尺寸 (mm)
w, h, l = 600, 1700, 400
box = {
'center': center,
'dimensions': [w, h, l],
'orientation': [0, 0, 0]
}
boxes.append(box)
return boxes


# 测试
if __name__ == "__main__":
# 模拟4相机系统
intrinsics = [{'fx': 615, 'fy': 615, 'cx': 320, 'cy': 240}] * 4
extrinsics = [np.eye(4)] * 4 # 简化

pipeline = PseudoLabelPipeline(intrinsics, extrinsics)

# 模拟输入
rgb = np.random.randint(0, 255, (4, 480, 640, 3), dtype=np.uint8)
depth = np.random.randint(500, 2000, (4, 480, 640), dtype=np.uint16)
lidar = np.random.randn(10000, 3)

result = pipeline.process_frame(rgb, depth, lidar)
print(f"检测到的3D包围盒: {len(result['boxes_3d'])}")

基准模型评测

论文使用 Lift-Splat-Shoot (LSS) 和 BEVFusion 作为基准模型:

模型 输入 mAP 内存 推理速度
Lift-Splat-Shoot 4×RGB 38.2 4.2GB 85ms
BEVFusion 4×RGB+LiDAR 52.7 6.8GB 120ms
单视角YOLO 1×RGB 31.5 1.5GB 25ms

IMS开发启示

1. 商用车内监测方案

应用场景 推荐方案 关键差异
城市巴士 多视角+LiDAR 大空间、多遮挡
长途客车 2-3相机+DMS 侧重驾驶员+乘客
货运卡车 DMS+1个OMS 侧重驾驶员
Robotaxi 4+相机全舱 侧重乘客+遗留物

2. 公共交通特有需求

  • 安全事件检测: 打架、抢劫、破坏公物
  • 无障碍辅助: 轮椅识别与辅助
  • 乘客计数: 上下车流量
  • 遗留物品: 到站提醒

3. 数据集构建建议

步骤 论文方案 IMS建议
传感器 RealSense D435i × 4 ✅ 性价比高
同步 NTP + ROS 2 ✅ 已有方案
标注 伪标签(SAM3) 需人工修正
格式 nuScenes ✅ 标准化

来源:arXiv 2606.11739 | 关键词:multi-view, in-cabin monitoring, 3D pose, public transport, nuScenes