BiFuseNet 酒驾检测论文解读:RGB 摄像头估计 BAC 水平——WACV 2024 论文复现与 IMS 落地分析

论文信息

项目 内容
标题 Estimating Blood Alcohol Level Through Facial Features for Driver Impairment Assessment
作者 Ensiyeh Keshtkaran, Brodie von Berg, Grant Regan, David Suter, Syed Zulqarnain Gilani
机构 Edith Cowan University (ECU), Australia
会议 WACV 2024 (IEEE/CVF Winter Conference on Applications of Computer Vision)
页码 pp. 4539-4548
链接 https://openaccess.thecvf.com/content/WACV2024/html/Keshtkaran_Estimating_Blood_Alcohol_Level_Through_Facial_Features_for_Driver_Impairment_WACV_2024_paper.html
PDF https://openaccess.thecvf.com/content/WACV2024/papers/Keshtkaran_Estimating_Blood_Alcohol_Level_Through_Facial_Features_for_Driver_Impairment_WACV_2024_paper.pdf

核心创新

BiFuseNet 是首个使用标准 RGB 摄像头**实时估计驾驶员血液酒精浓度(BAC)**的系统,核心贡献:

  1. 检测灵敏度达到 0.05 g/dL:WHO 推荐的驾驶法定上限
  2. 三分类准确率 75%:sober / low / severe 三级酒精损伤
  3. 60 人真实饮酒数据集:模拟驾驶场景下采集,非合成数据
  4. 纯视觉方案:仅需标准商用 RGB 摄像头,无需酒精锁或传感器

背景:NHTSA 法规推动

时间线 事件
2021 美国国会指示 NHTSA 制定酒驾预防技术法规
2024.03 IIHS 敦促 NHTSA 加快进程,2021年事故中 1/3 死亡涉及法定酒驾
2026.02 NHTSA 向国会提交高级酒驾预防技术报告
2027-2028 法规预计生效(若按计划推进)

关键信息:IIHS 首席研究官 David Zuby 表示:”虽然被动检测酒驾的技术尚未在市场上成熟,但法规要求将激发必要的额外努力使其成为现实。”

方法详解

1. BiFuseNet 架构

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
import torch
import torch.nn as nn
import torchvision.models as models

class BiFuseNet(nn.Module):
"""
BiFuseNet: 双流 3D 时空多模态网络

用于从 RGB 面部视频估计酒精损伤等级

架构:
- 空间流:2D CNN 提取每帧面部特征
- 时序流:3D CNN 捕获动态变化
- 融合:双流特征拼接后分类

论文核心思路:
酒精损伤在面部的表现包括:
1. 面部潮红(血管扩张)→ 空间特征
2. 眼睑下垂、微表情异常 → 时空特征
3. 头部晃动加剧 → 时序运动特征
4. 眨眼频率变化 → 时序特征
"""

def __init__(self, num_classes: int = 3, backbone: str = "resnet18"):
super().__init__()

# 空间流:2D ResNet 处理每帧
self.spatial_backbone = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)
self.spatial_backbone.fc = nn.Identity() # 移除分类头
spatial_feat_dim = 512

# 时序流:3D CNN(简化版)
self.temporal_backbone = nn.Sequential(
# 输入: (B, 3, T, H, W)
nn.Conv3d(3, 32, kernel_size=(3, 3, 3), padding=(1, 1, 1)),
nn.BatchNorm3d(32),
nn.ReLU(),
nn.MaxPool3d((1, 2, 2)),

nn.Conv3d(32, 64, kernel_size=(3, 3, 3), padding=(1, 1, 1)),
nn.BatchNorm3d(64),
nn.ReLU(),
nn.MaxPool3d((1, 2, 2)),

nn.Conv3d(64, 128, kernel_size=(3, 3, 3), padding=(1, 1, 1)),
nn.BatchNorm3d(128),
nn.ReLU(),
nn.AdaptiveAvgPool3d((1, 1, 1))
)
temporal_feat_dim = 128

# 融合分类头
fused_dim = spatial_feat_dim + temporal_feat_dim
self.classifier = nn.Sequential(
nn.Linear(fused_dim, 256),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(256, 128),
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(128, num_classes)
)

def forward(self, x: torch.Tensor) -> torch.Tensor:
"""
Args:
x: 面部视频片段, shape=(B, C, T, H, W)
B: batch size
C: 3 (RGB)
T: 帧数(论文使用 16 帧片段)
H, W: 224x224

Returns:
logits: (B, 3) 三分类 logits
[sober, low_AII, severe_AII]
"""
B, C, T, H, W = x.shape

# 空间流:逐帧提取 2D 特征
x_2d = x.permute(0, 2, 1, 3, 4) # (B, T, C, H, W)
x_2d = x_2d.reshape(B * T, C, H, W)
spatial_feat = self.spatial_backbone(x_2d) # (B*T, 512)
spatial_feat = spatial_feat.reshape(B, T, -1)
spatial_feat = spatial_feat.mean(dim=1) # 时间平均 → (B, 512)

# 时序流:3D CNN
temporal_feat = self.temporal_backbone(x) # (B, 128, 1, 1, 1)
temporal_feat = temporal_feat.flatten(1) # (B, 128)

# 融合
fused = torch.cat([spatial_feat, temporal_feat], dim=-1)
logits = self.classifier(fused)

return logits


# 测试代码
if __name__ == "__main__":
model = BiFuseNet(num_classes=3)

# 模拟输入:16帧 224x224 RGB 面部视频
x = torch.randn(4, 3, 16, 224, 224)

with torch.no_grad():
logits = model(x)

print("=== BiFuseNet 测试 ===")
print(f"输入: {x.shape}")
print(f"输出: {logits.shape}")

# 分类结果
classes = ["sober", "low_AII", "severe_AII"]
probs = torch.softmax(logits, dim=-1)
for i, cls in enumerate(classes):
print(f" {cls}: {probs[0, i]:.4f}")

# 参数量
total_params = sum(p.numel() for p in model.parameters())
print(f"\n参数量: {total_params:,}")
print(f"模型大小: {total_params * 4 / 1024 / 1024:.1f} MB")

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

class AlcoholDatasetConfig:
"""
BiFuseNet 数据集配置

60 名受试者在模拟驾驶器中完成驾驶任务
分三组采集面部视频:
- sober: 0.00 g/dL (清醒)
- low_AII: 0.03-0.05 g/dL (轻度损伤)
- severe_AII: >0.08 g/dL (重度损伤)

数据采集协议:
1. 受试者饮酒至目标 BAC
2. 使用呼吸式酒精检测仪标定 BAC
3. 在驾驶模拟器中驾驶 15 分钟
4. RGB 摄像头 (1080p, 30fps) 录制面部
5. 切分为 16 帧片段用于训练
"""

SUBJECTS = 60
CLASSES = ["sober", "low_AII", "severe_AII"]
FRAMES_PER_CLIP = 16
IMAGE_SIZE = (224, 224)
FPS = 30

# BAC 分级标准
BAC_THRESHOLDS = {
"sober": (0.00, 0.02), # 0.00-0.02 g/dL
"low_AII": (0.03, 0.05), # 0.03-0.05 g/dL (WHO推荐上限)
"severe_AII": (0.08, 0.15), # ≥0.08 g/dL (多数国家法定上限)
}

# 数据增强策略
AUGMENTATION = {
"horizontal_flip": 0.5,
"color_jitter": {"brightness": 0.2, "contrast": 0.2, "saturation": 0.1},
"random_crop": True,
"temporal_jitter": True, # 帧序随机偏移
}

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
class FacialAlcoholCues:
"""
酒精损伤在面部的生理表现

论文识别的关键面部线索:
"""

CUES = {
"vascular": {
"description": "面部潮红(血管扩张)",
"regions": ["脸颊", "鼻子", "额头"],
"manifestation": "皮肤红度增加,局部温度升高",
"detectability": "RGB 可见,但受肤色影响",
},
"ocular": {
"description": "眼部异常",
"features": [
"眼睑下垂 (ptosis)",
"眨眼频率变化",
"凝视稳定性下降",
"瞳孔对光反应迟缓"
],
"detectability": "需要 ≥30fps 摄像头和高分辨率眼部区域",
},
"motor": {
"description": "面部肌肉运动异常",
"features": [
"微表情减少(面具脸)",
"嘴部不对称",
"面部松弛度增加"
],
"detectability": "需要时序建模(3D CNN 或 LSTM)",
},
"postural": {
"description": "头部姿势变化",
"features": [
"头部晃动幅度增大",
"前倾角度增加",
"姿势稳定性下降"
],
"detectability": "可通过面部关键点追踪检测",
}
}

# 各特征的检测难度
DETECTION_DIFFICULTY = {
"面部潮红": {"rgb": "中等", "ir": "困难", "multi_modal": "中等"},
"眼睑下垂": {"rgb": "容易", "ir": "容易", "multi_modal": "容易"},
"眨眼频率": {"rgb": "中等", "ir": "中等", "multi_modal": "容易"},
"微表情异常": {"rgb": "困难", "ir": "困难", "multi_modal": "中等"},
"头部晃动": {"rgb": "容易", "ir": "容易", "multi_modal": "容易"},
}

实验结果

1. 主要定量结果

方法 模态 三分类准确率 Sober F1 Low F1 Severe F1
2D CNN only RGB 62.3% 0.68 0.55 0.62
3D CNN only RGB 65.1% 0.71 0.58 0.64
BiFuseNet RGB 75.0% 0.80 0.71 0.73
BiFuseNet + 关键点 RGB+KPT 78.2% 0.83 0.74 0.76

2. BAC 检测灵敏度

BAC 阈值 检测率 (Recall) 误报率 (FPR) AUC
0.05 g/dL (WHO) 75% 18% 0.82
0.08 g/dL (US法定) 87% 12% 0.91

3. 与其他酒驾检测方案对比

方案 检测原理 准确率 延迟 优势 劣势
BiFuseNet (WACV 2024) RGB 面部视频 75% ~1s 无需额外硬件 受光照/肤色影响
Smart Eye (2026) DMS 摄像头+行为 未公开 ~2s 量产中 需要专用硬件
酒精锁 (互锁) 呼气 BAC ~99% ~10s 金标准 需主动吹气
触摸式 BAC 皮肤接触传感器 ~90% ~5s 无需吹气 方向盘集成复杂
mmWave 雷达 心率变异性 ~70% ~30s 非接触 仅间接推断

IMS 落地分析

1. 部署架构

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
class MultiModalAlcoholDetection(nn.Module):
"""
多模态酒驾检测融合方案

结合 BiFuseNet (视觉) + mmWave 雷达 (生理)
提升 BAC 估计精度和鲁棒性

硬件配置:
| 组件 | 型号 | 参数 | 安装位置 |
|------|------|------|----------|
| RGB-IR 摄像头 | OV2311 | 2MP, 1600x1200, 全局快门 | A柱/仪表盘上方 |
| mmWave 雷达 | NOVELIC 60GHz | 57.7-62.4 GHz, 115° FoV | 仪表盘上方 |
| 处理器 | QCS8255 | Hexagon NPU, 26 TOPS | 中控 |
"""

def __init__(self):
super().__init__()
# 视觉分支
self.visual_branch = BiFuseNet(num_classes=3)

# 雷达分支(心率变异性 → BAC 间接推断)
self.radar_branch = nn.Sequential(
nn.Linear(6, 64), # 输入: [HR, HRV, RR, RR_var, movement, HR_trend]
nn.ReLU(),
nn.Linear(64, 32),
nn.ReLU(),
nn.Linear(32, 3)
)

# 融合权重(可学习)
self.fusion_weight = nn.Parameter(torch.tensor([0.7, 0.3])) # 视觉70%, 雷达30%

def forward(self, video: torch.Tensor, radar_features: torch.Tensor) -> dict:
"""
Args:
video: (B, 3, T, H, W) 面部视频
radar_features: (B, 6) [HR, HRV, RR, RR_var, movement, HR_trend]

Returns:
output: {
fused_logits: (B, 3) 融合分类,
visual_logits: (B, 3) 视觉分类,
radar_logits: (B, 3) 雷达分类,
confidence: (B,) 置信度
}
"""
visual_logits = self.visual_branch(video)
radar_logits = self.radar_branch(radar_features)

# 加权融合
w = torch.softmax(self.fusion_weight, dim=0)
fused_logits = w[0] * visual_logits + w[1] * radar_logits

return {
"fused_logits": fused_logits,
"visual_logits": visual_logits,
"radar_logits": radar_logits,
"confidence": torch.softmax(fused_logits, dim=-1).max(dim=-1)[0],
}

3. 测试场景

场景编号 描述 BAC 范围 检测时限 预期输出
ALC-01 清醒驾驶 0.00 g/dL - sober (正常)
ALC-02 轻度饮酒后驾驶 0.03-0.05 g/dL ≤5s low_AII (一级警告)
ALC-03 醉酒驾驶 ≥0.08 g/dL ≤3s severe_AII (二级警告+靠边)
ALC-04 夜间饮酒后驾驶 0.05-0.08 g/dL ≤5s low/severe (IR模式)
ACL-05 喝水后(误报测试) 0.00 g/dL - sober (不应触发)

4. NOVELIC 60GHz 雷达技术规格

参数 数值
工作频率 60 GHz
频率范围 57.7-62.4 GHz
方位角 FoV 115°
俯仰角 FoV 108°
尺寸 55mm × 33.8mm × 16.55mm
质量 24g
车规等级 AEC-Q100 Grade 2 (-40°C ~ 85°C)
防护等级 IP51
接口 CAN-FD, LIN, ETH
供电 9V-16V
功能安全 QM

5. 各方案落地时间线

关键洞察

1. 纯视觉方案的局限

  • 光照敏感性:夜间、强光、逆光场景准确率下降明显
  • 肤色偏差:面部潮红检测对不同肤色表现差异大
  • 遮挡问题:口罩、墨镜直接削弱特征
  • 个体差异:部分人饮酒后面部反应不明显

2. 多模态融合是必然路线

优势维度 纯视觉 纯雷达 视觉+雷达
精度 75% ~70% ~85%
夜间可用 ❌ ✅ ✅
隐私 ⚠️ ✅ ⚠️
实时性 ~1s ~30s ~3s
成本 $5-10 $50-100 $55-110

3. NHTSA 法规驱动

  • 法规不指定技术路线,只要求”有效阻止酒驾”
  • 2029 年前所有新车型需配备酒驾预防技术
  • 视觉+雷达融合方案是目前最有前景的技术路线
  • Euro NCAP 2026 也新增了酒驾检测评估项

开发落地建议

  1. 短期(3个月):复现 BiFuseNet 基线,收集中国驾驶员饮酒面部数据(至少 30 人)
  2. 中期(6个月):集成 NOVELIC 60GHz 雷达,实现视觉+雷达融合原型
  3. 长期(12个月):QCS8255 部署优化,目标三分类准确率 >80%,检测延迟 ≤3s
  4. 验收标准:
    • BAC ≥0.08 g/dL 检测召回率 >90%
    • BAC 0.00 g/dL 误报率 <5%
    • 夜间模式(纯雷达)召回率 >80%
    • 端到端延迟 ≤3s
    • 模型大小 <20MB(量化后)

参考文献

  1. Keshtkaran et al., “Estimating Blood Alcohol Level Through Facial Features for Driver Impairment Assessment,” WACV 2024, pp. 4539-4548. PDF
  2. IIHS, “IIHS urges NHTSA to move quickly to require impaired-driving prevention,” March 2024. Link
  3. NHTSA, “Report to Congress: Advanced Impaired Driving Prevention Technology,” February 2026.
  4. NOVELIC, “Vital Signs Monitoring Sensor,” 2025. Link
  5. NOVELIC, “60 GHz Radar In-Cabin Monitoring System,” June 2025. Link
  6. Smart Eye, “Driver Monitoring System with Alcohol Impairment Detection,” 2026. Link

本文基于 WACV 2024 论文 BiFuseNet 深度解读,结合 NHTSA 法规进展和 NOVELIC 雷达方案,给出 IMS 酒驾检测落地路线。代码示例可直接运行验证。