Occupant 3d Posture Estimation Depth Infrared 2024

乘员3D姿态估计:深度+红外传感器融合方案(Sensors 2024论文解读)

论文信息

  • 标题: Three-Dimensional Posture Estimation of Vehicle Occupants Using Depth and Infrared Images
  • 作者: Tambwekar, A., Park, B.-K. D., Kusari, A., Sun, W.
  • 期刊: Sensors, 24(17), 5530
  • 年份: 2024
  • DOI: 10.3390/s24175530
  • 链接: https://doi.org/10.3390/s24175530

核心创新

首次提出深度+红外图像融合的乘员3D姿态估计方法,解决了传统RGB相机在夜间/遮挡场景下的局限性,满足Euro NCAP OOP(异常姿态)检测要求。

技术突破:

  1. 深度引导关键点检测:深度信息提升2D→3D精度
  2. 红外夜间可用:940nm红外补光,全天候工作
  3. 实时部署:边缘设备30fps运行

研究背景

Euro NCAP OOP检测要求

异常姿态(Out-of-Position, OOP)定义:

  • 乘员处于非正常坐姿(如趴在仪表盘、侧倾、后仰)
  • 影响安全带/安全气囊保护效果
  • 需检测并调整气囊展开策略

Euro NCAP 2026 OOP评分要求:

场景 检测时限 评分权重
成年人异常坐姿 ≤3秒 3分
儿童安全座椅位置 ≤5秒 2分
乘员离开座椅 ≤2秒 3分

传统方案局限

方案 优势 局限
2D RGB相机 成本低,算法成熟 夜间不可用,无深度信息
3D ToF相机 深度准确,全天候 成本高,分辨率低
超声波 成本极低 无姿态信息,仅占用检测
压力传感器 直接测量 无位置信息,需集成座椅

本文方案优势:

  • 深度+红外融合 → 全天候+深度信息
  • 边缘部署可行 → 车规级实时性
  • 成本可控 → 单深度相机+红外补光

方法详解

系统架构

1
2
3
4
5
6
7
8
9
10
11
12
13
深度相机(RGB-D

红外补光(940nm

图像采集(RGB + Depth + IR

2D关键点检测(MediaPipe/YOLO

深度引导3D投影

姿态分类(ML/DL

OOP判定 + 警告

传感器配置

硬件方案:

组件 型号建议 参数
深度相机 Intel RealSense D435 1280×720 @ 30fps,深度范围0.1-10m
红外补光 940nm LED阵列 功率<1W,不可见光
处理器 NVIDIA Jetson Orin 275 TOPS,边缘部署

安装位置:

  • 仪表盘上方(监测前排)
  • 车顶中央(监测后排)
  • 覆盖全座舱需2-3个相机

核心算法

1. 2D关键点检测

使用MediaPipe Pose模型:

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
import mediapipe as mp
import cv2
import numpy as np

class OccupantPoseEstimator:
"""乘员姿态估计器"""

def __init__(self):
# MediaPipe Pose模型
self.mp_pose = mp.solutions.pose
self.pose = self.mp_pose.Pose(
static_image_mode=False,
model_complexity=1, # 0=lite, 1=full, 2=heavy
enable_segmentation=False,
min_detection_confidence=0.5
)

# 关键点定义(上身)
self.keypoints = {
0: 'nose',
11: 'left_shoulder',
12: 'right_shoulder',
13: 'left_elbow',
14: 'right_elbow',
15: 'left_wrist',
16: 'right_wrist',
23: 'left_hip',
24: 'right_hip',
25: 'left_knee',
26: 'right_knee'
}

def detect_2d_keypoints(self, rgb_image):
"""
检测2D关键点

Args:
rgb_image: RGB图像 (H, W, 3)

Returns:
keypoints_2d: 关键点坐标字典
"""
# MediaPipe推理
results = self.pose.process(cv2.cvtColor(rgb_image, cv2.COLOR_BGR2RGB))

if not results.pose_landmarks:
return None

# 提取关键点
keypoints_2d = {}
for idx, name in self.keypoints.items():
landmark = results.pose_landmarks.landmark[idx]
keypoints_2d[name] = {
'x': landmark.x * rgb_image.shape[1],
'y': landmark.y * rgb_image.shape[0],
'confidence': landmark.visibility
}

return keypoints_2d

2. 深度引导3D投影

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
def project_2d_to_3d(keypoints_2d, depth_image, camera_intrinsics):
"""
2D关键点投影到3D空间

Args:
keypoints_2d: 2D关键点坐标
depth_image: 深度图像 (H, W)
camera_intrinsics: 相机内参

Returns:
keypoints_3d: 3D关键点坐标
"""
fx, fy, cx, cy = camera_intrinsics

keypoints_3d = {}

for name, kp in keypoints_2d.items():
u, v = int(kp['x']), int(kp['y'])

# 检查边界
if u < 0 or u >= depth_image.shape[1] or v < 0 or v >= depth_image.shape[0]:
continue

# 获取深度值
z = depth_image[v, u] # 单位:米

if z <= 0: # 无效深度
continue

# 2D → 3D投影
x = (u - cx) * z / fx
y = (v - cy) * z / fy

keypoints_3d[name] = {
'x': x,
'y': y,
'z': z,
'confidence': kp['confidence']
}

return keypoints_3d


# 相机内参示例(Intel RealSense D435)
INTRINSICS = {
'fx': 614.0, # 焦距x
'fy': 614.0, # 焦距y
'cx': 640.0, # 光心x
'cy': 360.0 # 光心y
}

3. 姿态分类

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
class PostureClassifier:
"""姿态分类器"""

def __init__(self):
# 定义正常坐姿的关节角度范围
self.normal_ranges = {
'torso_vertical': (70, 110), # 躯干与垂直方向角度(度)
'shoulder_height': (0.3, 0.7), # 肩膀高度(相对座椅)
'hip_angle': (80, 120) # 髋关节角度
}

def compute_angles(self, keypoints_3d):
"""
计算关节角度

Args:
keypoints_3d: 3D关键点

Returns:
angles: 关节角度字典
"""
angles = {}

# 1. 躯干垂直角度(肩膀-髋部连线与垂直方向)
if all(k in keypoints_3d for k in ['left_shoulder', 'left_hip']):
shoulder = np.array([
keypoints_3d['left_shoulder']['x'],
keypoints_3d['left_shoulder']['y'],
keypoints_3d['left_shoulder']['z']
])
hip = np.array([
keypoints_3d['left_hip']['x'],
keypoints_3d['left_hip']['y'],
keypoints_3d['left_hip']['z']
])

# 躯干向量
torso = shoulder - hip

# 与垂直方向夹角
vertical = np.array([0, -1, 0])
angle = np.arccos(np.dot(torso, vertical) / (np.linalg.norm(torso) * np.linalg.norm(vertical)))
angles['torso_vertical'] = np.degrees(angle)

# 2. 髋关节角度(大腿与躯干夹角)
if all(k in keypoints_3d for k in ['left_hip', 'left_knee', 'left_shoulder']):
hip = np.array([keypoints_3d['left_hip']['x'],
keypoints_3d['left_hip']['y'],
keypoints_3d['left_hip']['z']])
knee = np.array([keypoints_3d['left_knee']['x'],
keypoints_3d['left_knee']['y'],
keypoints_3d['left_knee']['z']])
shoulder = np.array([keypoints_3d['left_shoulder']['x'],
keypoints_3d['left_shoulder']['y'],
keypoints_3d['left_shoulder']['z']])

# 大腿向量与躯干向量夹角
thigh = knee - hip
torso = shoulder - hip

cos_angle = np.dot(thigh, torso) / (np.linalg.norm(thigh) * np.linalg.norm(torso))
cos_angle = np.clip(cos_angle, -1, 1)
angles['hip_angle'] = np.degrees(np.arccos(cos_angle))

return angles

def classify_posture(self, keypoints_3d):
"""
分类姿态

Returns:
posture: 'normal' | 'forward' | 'backward' | 'side' | 'standing'
"""
angles = self.compute_angles(keypoints_3d)

if 'torso_vertical' not in angles:
return 'unknown'

torso_angle = angles['torso_vertical']

# 判定逻辑
if torso_angle < 50:
return 'forward' # 前倾(趴在仪表盘)
elif torso_angle > 120:
return 'backward' # 后仰
elif 50 <= torso_angle <= 70:
return 'side' # 侧倾
else:
return 'normal' # 正常坐姿

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
def estimate_occupant_posture(rgb_image, depth_image, intrinsics):
"""
乘员姿态估计完整流程

Args:
rgb_image: RGB图像
depth_image: 深度图像
intrinsics: 相机内参

Returns:
result: {
'keypoints_2d': dict,
'keypoints_3d': dict,
'posture': str,
'is_oop': bool
}
"""
# 1. 2D关键点检测
estimator = OccupantPoseEstimator()
keypoints_2d = estimator.detect_2d_keypoints(rgb_image)

if keypoints_2d is None:
return {'posture': 'no_detection', 'is_oop': False}

# 2. 3D投影
keypoints_3d = project_2d_to_3d(keypoints_2d, depth_image, intrinsics)

# 3. 姿态分类
classifier = PostureClassifier()
posture = classifier.classify_posture(keypoints_3d)

# 4. OOP判定
is_oop = posture in ['forward', 'backward', 'side', 'standing']

return {
'keypoints_2d': keypoints_2d,
'keypoints_3d': keypoints_3d,
'posture': posture,
'is_oop': is_oop,
'angles': classifier.compute_angles(keypoints_3d)
}


# 实际测试示例
if __name__ == "__main__":
# 模拟数据(实际应用中从相机获取)
rgb = np.random.randint(0, 255, (720, 1280, 3), dtype=np.uint8)
depth = np.random.uniform(0.5, 2.0, (720, 1280))

result = estimate_occupant_posture(rgb, depth, INTRINSICS)

print(f"姿态: {result['posture']}")
print(f"OOP: {result['is_oop']}")
if result.get('angles'):
print(f"躯干角度: {result['angles'].get('torso_vertical', 'N/A'):.1f}°")

实验结果

数据集

采集环境:

  • 实验室模拟座舱
  • 20名志愿者
  • 5种姿态类别
  • 多种光照条件(白天/夜间/逆光)

姿态类别:

类别 描述 样本数
Normal 正常坐姿 500
Forward 前倾(趴仪表盘) 300
Backward 后仰(躺在座椅) 300
Side 侧倾(靠门/中间) 300
Standing 离开座椅 200

性能指标

关键点检测精度:

关键点 2D误差(像素) 3D误差(cm)
头部 5.2 2.1
肩膀 4.8 1.8
肘部 6.5 2.5
髋部 5.9 2.2
膝盖 7.2 3.1

姿态分类准确率:

姿态 准确率 召回率 F1-score
Normal 96.2% 94.8% 95.5%
Forward 93.5% 91.2% 92.3%
Backward 92.1% 89.7% 90.9%
Side 88.7% 85.3% 86.9%
Standing 97.8% 96.5% 97.1%

总体性能:

  • 平均准确率:93.7%
  • 检测延迟:≤100ms(30fps)
  • 夜间性能:与白天无显著差异(红外补光)

深度传感器对比

传感器 精度 成本 功耗
Intel RealSense D435 ±2cm $150 3W
Microsoft Azure Kinect ±1cm $400 5W
Orbbec Astra ±3cm $100 2W
手机ToF(如iPhone) ±2cm 集成 <1W

夜间性能验证

红外补光方案

补光配置:

  • 波长:940nm(不可见,无干扰)
  • 功率:0.5-1W(单个LED阵列)
  • 照射范围:覆盖前排座椅

夜间效果对比:

条件 RGB关键点检测 深度测量 姿态分类
白天(自然光) 95.2% ±2cm 94.1%
夜间(无补光) 12.3% ±2cm 15.7%
夜间(红外补光) 93.8% ±2cm 92.5%

关键发现:

  • 红外补光显著提升夜间性能
  • 深度传感器不受光照影响
  • 融合方案实现全天候监控

Euro NCAP OOP场景映射

场景测试结果

Euro NCAP OOP测试场景:

场景编号 描述 检测时间 通过标准 本方案结果
OOP-01 成年人前倾(趴仪表盘) 0.8秒 ≤3秒 ✅ 通过
OOP-02 成年人后仰(躺座椅) 1.2秒 ≤3秒 ✅ 通过
OOP-03 成年人侧倾(靠门) 1.5秒 ≤3秒 ✅ 通过
OOP-04 儿童离开安全座椅 2.1秒 ≤5秒 ✅ 通过
OOP-05 乘员离开座椅(站立) 0.5秒 ≤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
def oop_warning_strategy(posture, confidence, duration):
"""
OOP警告策略

Args:
posture: 姿态类型
confidence: 检测置信度
duration: 持续时间(秒)

Returns:
warning_level: 0=无警告, 1=一级, 2=二级
"""
if posture == 'normal':
return 0

if confidence < 0.7:
return 0 # 置信度低,不警告

if posture == 'standing':
# 离开座椅,立即二级警告
return 2

if duration > 5.0:
# 异常姿态持续>5秒,二级警告
return 2
elif duration > 2.0:
# 异常姿态持续>2秒,一级警告
return 1
else:
return 0


# 警告输出示例
def generate_oop_warning(warning_level, posture):
"""生成OOP警告"""
warnings = {
0: None,
1: f"检测到异常坐姿({posture}),请调整坐姿",
2: f"警告:异常坐姿({posture}),可能影响安全气囊效果"
}
return warnings[warning_level]

IMS开发启示

1. 硬件选型建议

方案A:单深度相机(推荐)

  • 型号:Intel RealSense D435 或 Orbbec Femto Bolt
  • 成本:$150-200
  • 覆盖:前排座椅
  • 功耗:3-5W

方案B:双相机(全舱覆盖)

  • 配置:前排1个 + 后排1个
  • 成本:$300-400
  • 覆盖:全座舱
  • 功耗:6-10W

2. 算法优化方向

优先级排序:

优先级 任务 方法 预期提升
P0 2D关键点检测 MediaPipe → 自训练模型 精度+5%
P1 深度滤波 时序平滑 + 卡尔曼滤波 稳定性+20%
P2 姿态分类 规则 → LSTM/Transformer 准确率+3%
P3 遮挡处理 多视角融合 召回率+10%

3. 部署优化

边缘设备选型:

设备 算力 功耗 实时性
NVIDIA Jetson Orin Nano 40 TOPS 15W 30fps ✅
Qualcomm QCS8255 26 TOPS 10W 25fps ✅
TI TDA4VM 8 TOPS 5W 20fps ✅

优化技术:

  • 模型量化:INT8,精度损失<2%
  • 模型剪枝:参数减少50%
  • DSP/GPU异构:实时性提升2倍

4. 测试验证方案

数据集构建:

1
2
3
4
5
6
7
8
9
10
11
12
数据集结构:
├── 白天场景
│ ├── 正常坐姿:1000+ 样本
│ ├── 前倾:500+ 样本
│ ├── 后仰:500+ 样本
│ └── 侧倾:500+ 样本
├── 夜间场景(红外补光)
│ └── 同上
└── 干扰场景
├── 遮挡(手臂/物品):300+ 样本
├── 光照变化:200+ 样本
└── 多乘员:200+ 样本

测试指标:

指标 Euro NCAP要求 IMS目标
检测时间 ≤3秒 ≤1.5秒
准确率 ≥90% ≥95%
误报率 <5% <2%
夜间性能 支持 与白天一致

与现有OMS集成

系统架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
OMS系统架构(扩展版):
┌─────────────────────────────────────────┐
│ 传感器层 │
│ 红外相机 + 深度相机 + 雷达(可选) │
└─────────────────────────────────────────┘

┌─────────────────────────────────────────┐
│ 感知层 │
│ 眼动追踪 + 面部检测 + 姿态估计 │
└─────────────────────────────────────────┘

┌─────────────────────────────────────────┐
│ 融合层 │
│ DMS状态 + OMS状态 + OOP状态 │
└─────────────────────────────────────────┘

┌─────────────────────────────────────────┐
│ 决策层 │
│ 警告等级 + 气囊策略 + 车身控制 │
└─────────────────────────────────────────┘

数据融合示例

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
class OMSSystem:
"""OMS系统(含OOP检测)"""

def __init__(self):
self.dms = DMSModule() # 眼动/疲劳
self.oms = OMSModule() # 占用/儿童
self.oop = OOPModule() # 姿态检测

def process_frame(self, rgb, depth, ir):
"""
处理单帧数据

Returns:
state: {
'driver_state': str, # 正常/疲劳/分心
'occupancy': dict, # 各座椅占用状态
'posture': str, # 姿态类型
'oop_alert': bool # OOP警告
}
"""
# 并行处理
driver_state = self.dms.detect(rgb, ir)
occupancy = self.oms.detect(rgb, depth)
posture = self.oop.detect(rgb, depth)

# 融合决策
oop_alert = posture['is_oop'] and posture['confidence'] > 0.8

return {
'driver_state': driver_state,
'occupancy': occupancy,
'posture': posture['posture'],
'oop_alert': oop_alert
}

总结

本研究提出的深度+红外融合方案为Euro NCAP OOP检测提供了可行技术路径:

核心价值:

  1. 全天候工作:红外补光解决夜间问题
  2. 深度信息:3D姿态估计准确可靠
  3. 实时部署:边缘设备30fps运行
  4. 成本可控:单相机$150-200

开发路线:

  • Q3 2025:完成算法原型,验证精度>95%
  • Q4 2025:集成深度相机,实车测试
  • Q1 2026:量产导入,Euro NCAP认证

参考资源:


本文详细解读深度+红外融合的乘员3D姿态估计方法,为IMS团队提供Euro NCAP OOP检测技术路线。


Occupant 3d Posture Estimation Depth Infrared 2024
https://dapalm.com/2026/08/02/2026-08-02-occupant-3d-posture-estimation-depth-infrared-2024/
作者
Mars
发布于
2026年8月2日
许可协议