DriverMHG + HandyNet 联合解读:驾驶员手部感知——从微手势交互到3D定位分析的完整方案

DriverMHG + HandyNet 联合解读:驾驶员手部感知

1. 为什么驾驶员手部感知重要

传统DMS聚焦”看脸”(疲劳/分心),但驾驶员的手部行为包含丰富信息:

手部行为 DMS价值 Euro NCAP映射
手离方向盘 L2接管准备度 D-04 接管
手持手机 分心检测 D-02/D-03
微手势交互 减少视觉分心 UI交互
手位置3D定位 OOP/安全带检测 OOP
手持物体 行为识别 DBR

2. DriverMHG:方向盘微手势数据集

2.1 数据集概况

维度 数值
被试 25人(13男/12女)
手势类别 5+2类
模态 RGB + IR + Depth
分辨率 320×240 @ 30fps
光照条件 3种
手部 双手同步(左右独立)

2.2 手势定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
DRIVER_MHG_CLASSES = {
0: {"name": "Swipe Right", "chinese": "右滑", "use_case": "切下一首音乐"},
1: {"name": "Swipe Left", "chinese": "左滑", "use_case": "切上一首音乐"},
2: {"name": "Flick Down", "chinese": "下拨", "use_case": "音量减"},
3: {"name": "Flick Up", "chinese": "上拨", "use_case": "音量加"},
4: {"name": "Tap", "chinese": "轻点", "use_case": "确认/播放暂停"},
5: {"name": "None", "chinese": "静止", "use_case": "正常握盘"},
6: {"name": "Other", "chinese": "其他", "use_case": "随机转向动作"},
}

# 关键特性:微手势 = 手不离方向盘
MICRO_GESTURE_PROPERTIES = {
"hands_on_wheel": True, # 始终握盘
"spatial_range_cm": 5, # 5cm内移动
"temporal_duration_ms": "300-800", # 0.3-0.8秒
"visibility": "low_contrast", # 低对比度
"safety_benefit": "eyes_on_road", # 保持视线在路上
}

2.3 实时识别框架

graph TB
    A[输入视频] --> B[视频分割<br/>左/右手分支]
    B --> C[左手3D-CNN]
    B --> D[右手3D-CNN]
    
    C --> E[3D-MobileNetV2<br/>或3D-ShuffleNetV2]
    D --> E
    
    E --> F[滑动窗口<br/>32帧]
    F --> G[在线识别算法<br/>转移概率]
    G --> H{多模态融合}
    
    H --> I[RGB分数]
    H --> J[IR分数]
    H --> K[Depth分数]
    
    I & J & K --> L[分数级融合]
    L --> M[手势分类输出]

2.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
import torch
import torch.nn as nn
from typing import Tuple

class MicroGesture3DCNN(nn.Module):
"""
3D-MobileNetV2 for Driver Micro Hand Gesture Recognition

关键设计:
- 3D深度可分离卷积(减少参数)
- 双分支(左/右手独立)
- 32帧时序窗口
"""

def __init__(self, num_classes: int = 7, input_channels: int = 3):
super().__init__()

# 3D深度可分离卷积块
def conv_bn(inp, oup, kernel=3, stride=1, groups=1):
return nn.Sequential(
nn.Conv3d(inp, oup, kernel, stride, kernel//2, groups=groups, bias=False),
nn.BatchNorm3d(oup),
nn.ReLU6(inplace=True),
)

def conv_dw(inp, oup, kernel=3, stride=1):
return nn.Sequential(
nn.Conv3d(inp, inp, kernel, stride, kernel//2, groups=inp, bias=False),
nn.BatchNorm3d(inp),
nn.ReLU6(inplace=True),
nn.Conv3d(inp, oup, 1, 1, 0, bias=False),
nn.BatchNorm3d(oup),
nn.ReLU6(inplace=True),
)

self.features = nn.Sequential(
conv_bn(input_channels, 32, kernel=7, stride=2), # (B,32,T/2,H/2,W/2)
conv_dw(32, 64, stride=2), # (B,64,T/4,H/4,W/4)
conv_dw(64, 128, stride=2), # (B,128,T/8,H/8,W/8)
conv_dw(128, 128, stride=1),
conv_dw(128, 256, stride=2),
conv_dw(256, 256, stride=1),
nn.AdaptiveAvgPool3d(1),
)

self.classifier = nn.Sequential(
nn.Dropout(0.2),
nn.Linear(256, num_classes),
)

def forward(self, x: torch.Tensor) -> torch.Tensor:
"""
Args:
x: (B, C, T, H, W) — T=32帧
Returns:
logits: (B, num_classes)
"""
x = self.features(x)
x = x.flatten(1)
return self.classifier(x)


class MultiModalFusion:
"""
分数级融合 (RGB + IR + Depth)

论文发现:IR > RGB > Depth(车载环境)
"""

def __init__(self, weights: dict = None):
self.weights = weights or {"rgb": 0.25, "ir": 0.50, "depth": 0.25}

def fuse(
self,
rgb_scores: torch.Tensor,
ir_scores: torch.Tensor,
depth_scores: torch.Tensor,
) -> torch.Tensor:
"""
分数级加权融合

IR权重最高(91.56%准确率)
Depth权重最低(强光下性能差)
"""
fused = (
self.weights["rgb"] * rgb_scores +
self.weights["ir"] * ir_scores +
self.weights["depth"] * depth_scores
)
return fused


class OnlineRecognition:
"""
在线识别算法

使用滑动窗口+转移概率:
- 不需要独立检测器
- 从分类器分数直接检测手势
"""

def __init__(
self,
window_size: int = 32,
stride: int = 4,
transition_threshold: float = 0.5,
):
self.window_size = window_size
self.stride = stride
self.transition_threshold = transition_threshold

def process_stream(
self,
score_stream: torch.Tensor, # (T, num_classes) 连续分数
) -> list:
"""
在线流式识别

Returns:
events: [{"gesture": str, "time": int, "confidence": float}]
"""
events = []
T = len(score_stream)

for t in range(0, T - self.window_size, self.stride):
window = score_stream[t:t + self.window_size]

# 转移概率分析
mean_scores = window.mean(dim=0)
max_class = mean_scores.argmax().item()
max_score = mean_scores[max_class].item()

if max_class != 5 and max_score > self.transition_threshold: # 非"None"
# 检查是否为新事件
if not events or events[-1]["gesture"] != max_class:
events.append({
"gesture": max_class,
"time": t,
"confidence": max_score,
})

return events


# 测试
if __name__ == "__main__":
model = MicroGesture3DCNN(num_classes=7)

# 模拟32帧输入
x = torch.randn(4, 3, 32, 120, 160)
output = model(x)
print(f"输出: {output.shape}") # (4, 7)
print(f"参数: {sum(p.numel() for p in model.parameters()) / 1e6:.1f}M")

# 多模态融合
fusion = MultiModalFusion()
rgb = torch.softmax(torch.randn(4, 7), dim=1)
ir = torch.softmax(torch.randn(4, 7), dim=1)
depth = torch.softmax(torch.randn(4, 7), dim=1)
fused = fusion.fuse(rgb, ir, depth)
print(f"融合输出: {fused.shape}")

2.5 关键结果

模态 离线准确率 在线准确率 说明
RGB 88.12% 73.50% 受光照影响
IR 91.56% 74.20% 最佳,光照无关
Depth 76.49% 56.49% 强光下失效
融合 92.34% 76.80% 分数级融合
骨干网络 参数量 速度(Titan XP) Jetson TX2
3D-MobileNetV2 0.2x ~0.2M 350+ clips/s 可用
3D-MobileNetV2 1.0x ~2M 150 clips/s ~30fps
3D-ShuffleNetV2 ~1M 200 clips/s ~40fps

3. HandyNet:手部检测/分割/3D定位

3.1 系统概览

维度 数值
任务 检测+分割+3D定位+物体识别
输入 Depth-only(隐私保护)
标注 色键自动标注
数据量 128,317帧 / 219,000手实例
被试 10人
骨干 Mask R-CNN + ResNet-50 + FPN
速度 ~15Hz (Titan X)

3.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
class ChromaKeyAnnotation:
"""
HandyNet 色键标注法

原理:
1. 驾驶员戴绿色手套+红色腕带
2. RGB-D同步采集
3. 颜色减法自动生成分割mask
4. mask关联到depth图训练
5. 部署时不需手套(depth-only)

优势:1天完成原来需数周的人工标注
"""

def __init__(self):
self.green_lower = (35, 50, 50) # HSV绿
self.green_upper = (85, 255, 255)
self.red_lower1 = (0, 50, 50) # HSV红低
self.red_upper1 = (10, 255, 255)
self.red_lower2 = (170, 50, 50) # HSV红高
self.red_upper2 = (180, 255, 255)

def generate_mask(self, rgb_frame):
"""
从RGB帧自动生成手部mask

Returns:
hand_mask: 手部区域
wrist_mask: 腕部区域(用于定位)
"""
import cv2
hsv = cv2.cvtColor(rgb_frame, cv2.COLOR_BGR2HSV)

# 绿色手套 → 手部
hand_mask = cv2.inRange(hsv, self.green_lower, self.green_upper)

# 红色腕带 → 腕部
red_mask1 = cv2.inRange(hsv, self.red_lower1, self.red_upper1)
red_mask2 = cv2.inRange(hsv, self.red_lower2, self.red_upper2)
wrist_mask = cv2.bitwise_or(red_mask1, red_mask2)

# 清理噪声
hand_mask = cv2.morphologyEx(hand_mask, cv2.MORPH_OPEN,
cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)))

return hand_mask, wrist_mask

def map_to_depth(self, hand_mask, depth_frame):
"""
将RGB mask映射到depth图

关键:训练时用mask,部署时用depth-only
"""
# 需要RGB-D对齐
depth_hand = depth_frame.copy()
depth_hand[hand_mask == 0] = 0 # 非手区域归零
return depth_hand


# 3D定位原理
def hand_3d_localization(depth_hand, camera_intrinsics):
"""
从depth图计算手部3D坐标

Args:
depth_hand: 手部区域depth图
camera_intrinsics: (fx, fy, cx, cy)

Returns:
hand_3d: (x, y, z) 手部中心3D坐标(米)
"""
import numpy as np

fx, fy, cx, cy = camera_intrinsics

# 手部像素区域
ys, xs = np.where(depth_hand > 0)
if len(xs) == 0:
return None

# 中心点
u, v = xs.mean(), ys.mean()
z = depth_hand[ys.astype(int), xs.astype(int)].mean() / 1000.0 # mm→m

# 像素→3D
x = (u - cx) * z / fx
y = (v - cy) * z / fy

return np.array([x, y, z])


# 测试
if __name__ == "__main__":
annotator = ChromaKeyAnnotation()

# 模拟depth手部区域
depth = np.random.randint(500, 1500, (240, 320))
mask = np.zeros((240, 320), dtype=np.uint8)
mask[100:150, 80:130] = 255 # 手部区域

depth_hand = depth.copy()
depth_hand[mask == 0] = 0

intrinsics = (525, 525, 160, 120) # 近似Kinect参数
pos_3d = hand_3d_localization(depth_hand, intrinsics)

if pos_3d is not None:
print(f"手部3D坐标: x={pos_3d[0]:.2f}m, y={pos_3d[1]:.2f}m, z={pos_3d[2]:.2f}m")

# 计算到方向盘距离
steering_wheel_pos = np.array([0.3, -0.2, 0.8]) # 推断方向盘位置
distance = np.linalg.norm(pos_3d - steering_wheel_pos)
print(f"到方向盘距离: {distance:.2f}m")

3.3 HandyNet架构

graph TB
    A[Depth Image<br/>单通道] --> B[ResNet-50 + FPN<br/>骨干网络]
    
    B --> C[RPN<br/>区域提议]
    C --> D[标准RoI<br/>紧致框]
    C --> E[RoI+<br/>扩展50%]
    
    D --> F[分割头<br/>手部mask]
    E --> G[分类头<br/>手持物体识别]
    
    F --> H[2D手部mask]
    G --> I[物体类别<br/>手机/瓶子/无]
    
    H --> J[3D定位<br/>depth→3D坐标]
    J --> K[到方向盘距离<br/>到手距离]
    
    I & K --> L[驾驶员状态评估]

4. 两个系统对比

维度 DriverMHG HandyNet
目标 微手势分类 手部检测+3D定位
输入 RGB+IR+Depth Depth-only
方法 3D-CNN分类 Mask R-CNN
手势类型 5类微手势 手+物体检测
精度 IR 91.56% Mask AP 42.9
速度 350+ clips/s 15 Hz
标注 人工 色键自动
部署 嵌入式友好 GPU级

5. IMS 开发启示

5.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
# IMS 手部感知模块配置
IMS_HAND_PERCEPTION = {
"module_1_micro_gesture": {
"purpose": "方向盘交互控制",
"sensor": "IR camera (940nm)",
"model": "3D-MobileNetV2 0.5x",
"classes": ["swipe_left", "swipe_right", "flick_up", "flick_down", "tap", "none"],
"latency_target": "<50ms",
"deploy": "Qualcomm QCS8255 NPU",
},
"module_2_hand_detection": {
"purpose": "安全状态检测(手离盘/持物)",
"sensor": "Depth camera",
"model": "Mask R-CNN lite",
"outputs": ["hand_mask", "3d_position", "held_object"],
"latency_target": "<100ms",
"deploy": "Qualcomm QCS8255 NPU",
},
"module_3_steering_grip": {
"purpose": "L2/L3接管准备度",
"sensor": "steering_wheel_capacitive + IR camera",
"outputs": ["hands_on_wheel", "grip_quality", "hand_position"],
"latency_target": "实时",
},
}

5.2 Euro NCAP 映射

Euro NCAP 手部感知支持 方案
D-02 手持手机 ✅ HandyNet物体识别 Depth+分类
D-03 打字操作 ⚠️ 需扩展 手指级追踪
D-04 接管准备 ✅ 手离盘检测 3D定位到盘距离
L2/L3 接管 ✅ 握盘检测 电容+IR双重

5.3 传感器建议

传感器 用途 安装位置 成本
IR摄像头(940nm) 微手势+面部DMS 转向柱/A柱
Depth摄像头 3D手部定位 车顶/中控 中高
方向盘电容 握盘检测 方向盘
力矩传感器 转向微修正 方向盘 已有

6. 验证测试场景

场景ID 条件 模块 预期
MG-T01 右滑手势(IR模式) DriverMHG ≤100ms识别
MG-T02 轻点手势(暗光) DriverMHG IR模式正常
MG-T03 正常握盘(非手势) DriverMHG 不误触发
HN-T01 手持手机 HandyNet 检测+识别手机
HN-T02 双手握盘 HandyNet 双手mask+3D定位
HN-T03 手离盘 HandyNet 距离>15cm触发警告

7. 局限性

系统 局限 缓解
DriverMHG 在线73-74%(离线91%+) 更强时序建模
DriverMHG 5类手势有限 需扩展手势集
HandyNet 15Hz不够实时 需轻量化
HandyNet “紧握手”检测失败 时序信息改善
两者 无乘员检测 需扩展

8. 结论

DriverMHG + HandyNet 联合方案覆盖了驾驶员手部感知的全链路:

  1. DriverMHG:微手势交互(5类/IR 91.56%/嵌入式350fps)
  2. HandyNet:手部检测/3D定位/物体识别(Depth-only/色键标注/128K帧)
  3. IR模态最优:微手势识别IR>RGB>Depth(车载环境)
  4. 色键标注高效:1天完成原需数周的手部分割标注
  5. 隐私保护:IR/Depth不泄露面部细节

IMS启示: DMS不能只看脸。手部感知是DMS的”第二只眼”——微手势交互减少视觉分心,3D手部定位支撑接管准备度和手持物体检测。建议IR+Depth双模态配置。


参考文献

  • DriverMHG: arXiv 2020, OpenReview JV7fPdNYFa
  • HandyNet: CVPR 2018
  • 3D-MobileNetV2: MobileNetV2, CVPR 2018
  • Mask R-CNN: He et al., ICCV 2017
  • Euro NCAP 2026 OMS Protocol (v1.0)

DriverMHG + HandyNet 联合解读:驾驶员手部感知——从微手势交互到3D定位分析的完整方案
https://dapalm.com/2026/09/16/2026-09-16-drivermhg-handynet-driver-hand-perception-micro-gesture-ims/
作者
Mars
发布于
2026年9月16日
许可协议