goVISCAN多光谱非接触生命体征传感器:10cm尺寸如何让座舱健康感知无处不在

Fraunhofer IOF技术解读 — 9通道多光谱微透镜阵列,10×7.5×2.5cm,非接触测量心率/呼吸/血氧

技术概述

2026年9月,Fraunhofer IOF(Jena)在”Advanced Multimodal Imaging”(AMI)研究联盟中发布 goVISCAN — 紧凑型非接触多光谱生命体征传感器。

参数 goVISCAN 传统rPPG摄像头 优势
尺寸 10×7.5×2.5cm 标准摄像头 ✅ 超紧凑
测量距离 70-130cm 50-100cm ✅ 更远
视场角 40° ~60° ⚠️ 较窄
光谱通道 9通道 3通道(RGB) ✅ 3×信息
心率误差 2.8 bpm 5-10 bpm ✅ 更准
呼吸误差 1.3 breaths/min 2-4 ✅ 更准
血氧误差 3.8个百分点 不可测 ✅ 突破
运动鲁棒性 ✅ 设计目标 ❌ 运动退化 ✅
光照鲁棒 ✅ 多光谱+LED ❌ 依赖环境 ✅

核心技术:9通道微透镜阵列

多光谱rPPG原理

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
"""
goVISCAN多光谱rPPG原理

传统rPPG(远程光电容积描记):
- 用RGB摄像头拍摄面部
- 提取皮肤微小亮度变化(<1%)
- 亮度变化由血液脉动引起
- 绿光通道最敏感(血红蛋白吸收峰)

goVISCAN多光谱rPPG:
- 9个光谱通道同时成像
- 不同波长对血液不同成分敏感:
* 绿光(~530nm): 血红蛋白吸收峰→心率
* 红光(~620nm): 氧合/脱氧血红蛋白差异→SpO₂
* NIR(~760-940nm): 穿透更深→呼吸(胸腔起伏)
- 多通道融合→更鲁棒、更准确
"""

import numpy as np
from typing import Tuple

class MultispectralrPPG:
"""多光谱rPPG信号提取"""

def __init__(self, n_channels=9):
self.n_channels = n_channels
# 光谱权重(简化)
# 通道0: 蓝(450nm), 1: 绿(530nm), 2: 红(620nm)
# 通道3-5: NIR, 通道6-8: 扩展
self.spectral_weights = np.array([
0.3, # 蓝 - 较弱rPPG信号
1.0, # 绿 - 最强rPPG(血红蛋白吸收峰)
0.8, # 红 - SpO₂计算
0.6, # NIR1 - 深层组织
0.5, # NIR2 - 呼吸
0.4, # NIR3 - 呼吸补充
0.3, 0.2, 0.1 # 扩展
])

def extract_heart_rate(self, multi_frames: np.ndarray, fps: int = 30) -> float:
"""
从多光谱视频帧提取心率

Args:
multi_frames: (N, 9, H, W) N帧×9通道
fps: 帧率

Returns:
heart_rate_bpm: 心率(次/分)
"""
# 1. 皮肤ROI检测(简化:使用绿光通道)
roi_mask = self._detect_skin(multi_frames[:, 1])

# 2. 每通道提取时序信号
signals = []
for ch in range(self.n_channels):
ch_frames = multi_frames[:, ch]
mean_val = np.array([
np.mean(ch_frames[i][roi_mask])
for i in range(len(ch_frames))
])
signals.append(mean_val)

signals = np.array(signals) # (9, N)

# 3. 加权融合
weighted = np.average(signals, axis=0, weights=self.spectral_weights)

# 4. 去趋势
weighted = weighted - np.convolve(weighted, np.ones(30)/30, mode='same')

# 5. FFT找心率频率
freqs = np.fft.rfftfreq(len(weighted), 1/fps)
spectrum = np.abs(np.fft.rfft(weighted))

# 心率范围: 0.7-3Hz (42-180 bpm)
mask = (freqs > 0.7) & (freqs < 3.0)
hr_freq = freqs[mask][np.argmax(spectrum[mask])]

return hr_freq * 60 # Hz→bpm

def extract_breathing(self, multi_frames: np.ndarray, fps: int = 30) -> float:
"""从NIR通道提取呼吸率"""
# NIR通道对胸腔运动更敏感
nir_channels = multi_frames[:, 3:6] # 通道3-5

# 提取低频信号(呼吸0.1-0.5Hz)
signals = nir_channels.mean(axis=(2, 3)) # (N, 3)
combined = signals.mean(axis=1)

# 去趋势
combined = combined - np.convolve(combined, np.ones(90)/90, mode='same')

# FFT
freqs = np.fft.rfftfreq(len(combined), 1/fps)
spectrum = np.abs(np.fft.rfft(combined))

mask = (freqs > 0.1) & (freqs < 0.5)
br_freq = freqs[mask][np.argmax(spectrum[mask])]

return br_freq * 60

def extract_spo2(self, multi_frames: np.ndarray) -> float:
"""从红光+NIR计算血氧饱和度"""
red_ch = multi_frames[:, 2].mean(axis=(1, 2)) # 红光
nir_ch = multi_frames[:, 4].mean(axis=(1, 2)) # NIR

# 比值法
ac_red = red_ch - np.mean(red_ch)
ac_nir = nir_ch - np.mean(nir_ch)

ratio = np.std(ac_red) / max(np.std(ac_nir), 1e-6)
spo2 = 110 - 25 * ratio # 经验公式

return max(70, min(100, spo2))

def _detect_skin(self, frames):
"""简化皮肤检测"""
return np.ones_like(frames[0], dtype=bool)


# 测试
if __name__ == "__main__":
rppg = MultispectralrPPG()

# 模拟数据
np.random.seed(42)
n_frames = 300 # 10秒@30fps
frames = np.random.randn(n_frames, 9, 64, 64) * 10 + 128

# 添加心率为72bpm的微弱脉动信号
t = np.arange(n_frames) / 30
pulse = np.sin(2 * np.pi * 1.2 * t) * 0.5 # 72bpm=1.2Hz
for ch in [1, 2]: # 绿光+红光
frames[:, ch] += pulse[np.newaxis, np.newaxis, :] * 0.1

hr = rppg.extract_heart_rate(frames)
br = rppg.extract_breathing(frames)
spo2 = rppg.extract_spo2(frames)

print("=== goVISCAN多光谱rPPG测试 ===")
print(f"心率: {hr:.1f} bpm (期望~72)")
print(f"呼吸: {br:.1f} breaths/min")
print(f"血氧: {spo2:.1f}%")
print(f"\n论文报告精度(vs脉搏血氧计):")
print(f" 心率误差: 2.8 bpm")
print(f" 呼吸误差: 1.3 breaths/min")
print(f" 血氧误差: 3.8 pp")

对座舱健康感知的价值

非接触vs接触式

方法 测量 接触 驾驶员接受度 座舱可行性
ECG胸带 心率 ✅ 需穿戴 ❌ 低 ❌
智能手表 心率 ✅ 需佩戴 ⚠️ 中 ⚠️
指尖血氧仪 SpO₂ ✅ 需夹指 ❌ 低 ❌
goVISCAN 心率+呼吸+SpO₂ ❌ 非接触 ✅ 高 ✅
标准rPPG 心率 ❌ 非接触 ✅ 高 ✅ 但无SpO₂

与座舱雷达的互补

传感器 心率 呼吸 SpO₂ 优势
goVISCAN(多光谱) ✅ 2.8bpm ✅ 1.3 ✅ 3.8pp 光学,高精度
60GHz雷达 ⚠️ 难 ✅ 好 ❌ 穿透毯子/衣物
ECG座椅 ✅ 好 ❌ ❌ 需接触
融合 最佳 最佳 可选 互补

IMS开发启示

1. 部署场景

2. 成本与集成

组件 成本 集成难度
goVISCAN传感器(量产估) ~$15-25 中(需顶灯安装)
DMS摄像头(VD56GA) ~$10 低
60GHz雷达(Murata) ~$12 中
多光谱+摄像头+雷达融合 ~$37-47 高

3. 与Fraunhofer生态

goVISCAN来自Fraunhofer IOF,与Fraunhofer IOSB的AktiMeter(3D骨骼)形成Fraunhofer座舱感知生态:

  • IOF: goVISCAN多光谱生命体征
  • IOSB: AktiMeter 3D骨骼行为分析
  • 两者互补:生理+行为

局限性

  1. 70-130cm距离:座舱安装位置需在DMS摄像头范围内
  2. 40°视场角:较窄,需对准驾驶员面部
  3. 运动鲁棒性:虽设计但剧烈运动仍可能退化
  4. 12人预研究:样本量小,需大规模验证
  5. SpO₂精度3.8pp:医疗级需≤2pp
  6. 光照干扰:阳光直射可能影响

结论

goVISCAN将多光谱rPPG从实验室推向实用:

  1. 10cm尺寸可嵌入座舱顶灯/后视镜
  2. 9通道多光谱同时测心率+呼吸+SpO₂——标准rPPG做不到
  3. 非接触驾驶员接受度高
  4. 与雷达互补——光学测心率/SpO₂,雷达测呼吸(穿透)

对IMS的启示:多光谱rPPG是座舱健康感知的下一个维度——从”看到了什么”到”身体怎么样”。


参考来源:

  • Fraunhofer IOF: goVISCAN (2026.09)
  • medicalxpress: Compact sensor contactless vital signs (2026.09.21)
  • Deutsches Gesundheitsportal: Vitaldaten ohne Berührung (2026.09.21)
  • AMI Research Consortium (RUBIN funded)