热成像舱内监测:驾驶员健康状态与损伤检测新维度

发布时间: 2026-04-15
关键词: Thermal Imaging、健康监测、发烧检测、损伤检测、DMS


研究背景

2026 年发表在《Traffic Injury Prevention》的研究首次验证了车载热成像系统检测驾驶员损伤的可行性

通过从特定面部区域提取时间平均温度值,可以检测驾驶员损伤状态。


热成像 DMS 应用场景

1. 发烧检测

应用 精度 传感器
体温筛查 ±0.3°C FLIR A500、Seek Scan
发烧预警 > 37.5°C 报警 红外热像仪
公共卫生 COVID-19 预防 热成像 + 人脸识别

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
┌─────────────────────────────────────────────────────┐
│ 热成像损伤检测原理 │
├─────────────────────────────────────────────────────┤
│ │
│ 正常状态 │
│ ──────── │
│ • 面部温度分布均匀 │
│ • 鼻尖温度略低于额头 │
│ • 温差 < 1°C │
│ │
│ 酒精损伤 │
│ ────────── │
│ • 面部毛细血管扩张 │
│ • 鼻尖温度升高 │
│ • 温差 > 2°C │
│ │
│ 疲劳状态 │
│ ────────── │
│ • 眼周温度变化 │
│ • 额头温度升高 │
│ • 温度波动增大 │
│ │
│ 生病状态 │
│ ────────── │
│ • 全面部温度升高 │
│ • 额头温度 > 37.5°C │
│ • 持续高温 │
│ │
└─────────────────────────────────────────────────────┘

热成像传感器选型

车载级热像仪

传感器 分辨率 精度 帧率 成本
FLIR Lepton 3.5 160×120 ±0.5°C 9 Hz $200-300
Seek Thermal Compact 206×156 ±0.5°C 15 Hz $250
Optris PI 450i 382×288 ±0.3°C 80 Hz $1000+
FLIR A500 640×480 ±0.3°C 30 Hz $2000+

性能对比

场景 低端热像仪 高端热像仪
发烧检测 ⭐⭐⭐ ⭐⭐⭐⭐⭐
损伤检测 ⭐⭐ ⭐⭐⭐⭐
成本敏感 ⭐⭐⭐⭐⭐ ⭐⭐

代码实现

面部温度提取

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

@dataclass
class FacialTemperature:
"""面部温度数据"""
forehead_temp: float # 额头温度
nose_temp: float # 鼻尖温度
left_cheek_temp: float # 左脸颊温度
right_cheek_temp: float # 右脸颊温度
eye_area_temp: float # 眼周温度
mean_temp: float # 平均温度
temp_variance: float # 温度方差

class ThermalFaceAnalyzer:
"""热成像面部温度分析器"""

def __init__(self):
# 人脸关键点检测器
self.landmark_detector = None # 需要加载模型

# 温度阈值
self.fever_threshold = 37.5 # °C
self.impairment_temp_diff = 2.0 # °C

def analyze(self,
thermal_image: np.ndarray,
facial_landmarks: Optional[Dict] = None) -> FacialTemperature:
"""分析面部温度

Args:
thermal_image: 热成像图像(温度矩阵)
facial_landmarks: 人脸关键点(可选)

Returns:
FacialTemperature: 面部温度数据
"""
# 如果没有提供关键点,使用简化方法
if facial_landmarks is None:
facial_landmarks = self._estimate_landmarks(thermal_image)

# 提取各区域温度
forehead_temp = self._extract_region_temp(
thermal_image, facial_landmarks, 'forehead'
)
nose_temp = self._extract_region_temp(
thermal_image, facial_landmarks, 'nose'
)
left_cheek_temp = self._extract_region_temp(
thermal_image, facial_landmarks, 'left_cheek'
)
right_cheek_temp = self._extract_region_temp(
thermal_image, facial_landmarks, 'right_cheek'
)
eye_area_temp = self._extract_region_temp(
thermal_image, facial_landmarks, 'eye_area'
)

# 计算统计数据
temps = [
forehead_temp, nose_temp, left_cheek_temp,
right_cheek_temp, eye_area_temp
]
mean_temp = np.mean(temps)
temp_variance = np.var(temps)

return FacialTemperature(
forehead_temp=forehead_temp,
nose_temp=nose_temp,
left_cheek_temp=left_cheek_temp,
right_cheek_temp=right_cheek_temp,
eye_area_temp=eye_area_temp,
mean_temp=mean_temp,
temp_variance=temp_variance
)

def _estimate_landmarks(self, thermal_image: np.ndarray) -> dict:
"""估计人脸关键点(简化)"""
h, w = thermal_image.shape

# 假设人脸在图像中央
center_x = w // 2
center_y = h // 2
face_width = w // 3
face_height = h // 2

return {
'forehead': (center_x, center_y - face_height // 4, face_width // 2, face_height // 8),
'nose': (center_x, center_y, face_width // 6, face_height // 6),
'left_cheek': (center_x - face_width // 3, center_y, face_width // 4, face_height // 4),
'right_cheek': (center_x + face_width // 3, center_y, face_width // 4, face_height // 4),
'eye_area': (center_x, center_y - face_height // 6, face_width // 2, face_height // 8),
}

def _extract_region_temp(self,
image: np.ndarray,
landmarks: dict,
region: str) -> float:
"""提取区域平均温度"""
x, y, w, h = landmarks[region]

# 边界检查
x = max(0, x - w // 2)
y = max(0, y - h // 2)
w = min(w, image.shape[1] - x)
h = min(h, image.shape[0] - y)

# 提取区域
roi = image[y:y+h, x:x+w]

# 返回平均温度
return np.mean(roi)


class ThermalHealthMonitor:
"""热成像健康监控器"""

def __init__(self):
self.face_analyzer = ThermalFaceAnalyzer()

# 历史数据
self.temp_history = []
self.history_window = 60 # 60 帧历史

def update(self, thermal_image: np.ndarray) -> dict:
"""更新监控状态

Returns:
{
'temperature': FacialTemperature,
'is_fever': bool,
'impairment_indicators': dict,
'health_alert': str
}
"""
# 分析面部温度
temp_data = self.face_analyzer.analyze(thermal_image)

# 记录历史
self.temp_history.append(temp_data)
if len(self.temp_history) > self.history_window:
self.temp_history.pop(0)

# 发烧检测
is_fever = temp_data.mean_temp > self.face_analyzer.fever_threshold

# 损伤指标
impairment_indicators = self._detect_impairment(temp_data)

# 健康警告
health_alert = self._generate_alert(is_fever, impairment_indicators)

return {
'temperature': temp_data,
'is_fever': is_fever,
'impairment_indicators': impairment_indicators,
'health_alert': health_alert
}

def _detect_impairment(self, temp_data: FacialTemperature) -> dict:
"""检测损伤指标"""
# 额头-鼻尖温差
temp_diff = temp_data.forehead_temp - temp_data.nose_temp

# 温度方差(疲劳指标)
fatigue_indicator = temp_data.temp_variance > 1.0

# 酒精损伤指标:温差大、鼻尖温度高
alcohol_indicator = temp_diff > self.face_analyzer.impairment_temp_diff

# 生病指标:整体温度高
illness_indicator = temp_data.mean_temp > 37.5

return {
'temp_diff': temp_diff,
'fatigue_indicator': fatigue_indicator,
'alcohol_indicator': alcohol_indicator,
'illness_indicator': illness_indicator,
'temp_variance': temp_data.temp_variance
}

def _generate_alert(self, is_fever: bool, indicators: dict) -> str:
"""生成健康警告"""
if is_fever:
return "⚠️ 发烧检测:体温异常升高,建议休息"

if indicators.get('alcohol_indicator'):
return "🚫 损伤检测:疑似酒精影响,禁止驾驶"

if indicators.get('fatigue_indicator'):
return "😴 疲劳检测:面部温度波动异常,建议休息"

return "✅ 健康状态正常"

RGB + 热成像融合

融合架构

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
class RGBThermalFusion:
"""RGB + 热成像融合系统"""

def __init__(self):
self.rgb_dms = DMSModule() # 标准 DMS
self.thermal_monitor = ThermalHealthMonitor()

# 融合权重
self.rgb_weight = 0.6
self.thermal_weight = 0.4

def process(self,
rgb_frame: np.ndarray,
thermal_frame: np.ndarray) -> dict:
"""融合处理

Args:
rgb_frame: RGB 图像
thermal_frame: 热成像图像

Returns:
{
'driver_state': dict,
'health_state': dict,
'fusion_result': dict
}
"""
# RGB DMS 分析
dms_result = self.rgb_dms.process(rgb_frame)

# 热成像健康分析
health_result = self.thermal_monitor.update(thermal_frame)

# 融合决策
fusion_result = self._fuse(dms_result, health_result)

return {
'driver_state': dms_result,
'health_state': health_result,
'fusion_result': fusion_result
}

def _fuse(self, dms_result: dict, health_result: dict) -> dict:
"""融合决策"""
# 疲劳检测融合
dms_fatigue = dms_result.get('fatigue_score', 0)
thermal_fatigue = 1.0 if health_result['impairment_indicators'].get('fatigue_indicator') else 0.0

fused_fatigue = (
dms_fatigue * self.rgb_weight +
thermal_fatigue * self.thermal_weight
)

# 损伤检测融合
# 热成像可以提供酒精损伤的补充证据
dms_impairment = dms_result.get('impairment_score', 0)
thermal_impairment = 1.0 if health_result['impairment_indicators'].get('alcohol_indicator') else 0.0

fused_impairment = max(dms_impairment, thermal_impairment)

# 健康警告
health_alert = health_result.get('health_alert', '')

return {
'fused_fatigue_score': fused_fatigue,
'fused_impairment_score': fused_impairment,
'is_fever': health_result['is_fever'],
'health_alert': health_alert,
'recommendation': self._get_recommendation(fused_fatigue, fused_impairment, health_result['is_fever'])
}

def _get_recommendation(self, fatigue: float, impairment: float, fever: bool) -> str:
"""获取建议"""
if fever:
return "暂停驾驶,休息或就医"
if impairment > 0.6:
return "禁止驾驶,疑似损伤"
if fatigue > 0.7:
return "建议休息"
return "正常驾驶"

Euro NCAP 关联

健康监测与 Euro NCAP

年份 健康监测要求 说明
2026 ⚠️ 鼓励 可能作为加分项
2027 ⚠️ 可能新增 发烧/疲劳检测
2028 ✅ 预计 健康监测纳入评分

得分机会

功能 预计得分
发烧检测 +2-3 分
健康状态监测 +2-3 分
损伤检测(热成像辅助) +3-5 分

传感器安装位置

最佳安装位置

位置 优势 劣势
仪表盘顶部 正对面部,精度高 可能遮挡视线
A 柱 不遮挡视线 侧面角度,精度降低
方向盘柱 近距离,高精度 随方向盘转动

参考资源