Nature 2025:毫米波雷达生命体征检测自适应卡尔曼滤波框架

Nature 2025:毫米波雷达生命体征检测自适应卡尔曼滤波框架

论文来源: Nature Scientific Reports
期刊: Scientific Reports, August 1, 2025
核心创新: 自适应卡尔曼滤波 + 平方根归一化 → 精准呼吸/心跳提取


论文信息

项目 内容
标题 Detection of vital signs based on millimeter wave radar
期刊 Nature Scientific Reports
创新 自适应卡尔曼滤波消除静态杂波和呼吸谐波

核心挑战:雷达生命体征提取

传统方法痛点:

1
2
3
4
5
6
7
8
9
10
干扰源:
- 静态杂波(座椅、车身反射)
- 呼吸谐波干扰心跳检测
- 身体大运动淹没微动信号
- 多目标信号混叠

传统滤波局限:
- 固定截止频率无法适应个体差异
- 呼吸频率变化导致谐波位置变化
- 静态杂波抑制不彻底

自适应卡尔曼滤波框架

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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
import numpy as np
from typing import Tuple

class AdaptiveKalmanVitalSigns:
"""
自适应卡尔曼滤波生命体征提取

Nature 2025 论文核心:
1. 定位胸部区域
2. 相位提取(慢时间维)
3. 信号叠加增强
4. 相位差分消除静态杂波
5. 自适应卡尔曼滤波
"""

def __init__(self,
fs: float = 20.0, # 帧率 Hz
breathing_range: Tuple[float, float] = (0.1, 0.5), # Hz
heartbeat_range: Tuple[float, float] = (0.8, 2.0)): # Hz
self.fs = fs
self.breathing_range = breathing_range
self.heartbeat_range = heartbeat_range

# 卡尔曼滤波器参数
self.Q_breath = 0.01 # 过程噪声(呼吸)
self.R_breath = 0.1 # 观测噪声(呼吸)

self.Q_heart = 0.001 # 过程噪声(心跳)
self.R_heart = 0.05 # 观测噪声(心跳)

def extract_phase(self,
radar_data: np.ndarray,
target_range_bin: int) -> np.ndarray:
"""
提取相位信号

Args:
radar_data: 雷达数据, shape=(num_chirps, num_range_bins)
target_range_bin: 目标距离bin

Returns:
phase: 相位序列, shape=(num_chirps,)
"""
# 提取目标bin的复数信号
complex_signal = radar_data[:, target_range_bin]

# 计算相位
phase = np.angle(complex_signal)

# 相位展开(避免2π跳变)
phase = np.unwrap(phase)

return phase

def phase_differencing(self, phase: np.ndarray) -> np.ndarray:
"""
相位差分消除静态杂波

静态杂波相位恒定,差分后为零

Args:
phase: 相位序列

Returns:
phase_diff: 差分后的相位
"""
phase_diff = np.diff(phase)

return phase_diff

def signal_enhancement(self,
phase_signals: list) -> np.ndarray:
"""
信号叠加增强

多个bin信号叠加,增强微弱信号

Args:
phase_signals: 多个bin的相位信号列表

Returns:
enhanced_signal: 增强后的信号
"""
# 叠加多个bin信号
enhanced = np.zeros_like(phase_signals[0])

for signal in phase_signals:
# 归一化后叠加
normalized = (signal - np.mean(signal)) / (np.std(signal) + 1e-6)
enhanced += normalized

return enhanced

def adaptive_kalman_filter(self,
signal: np.ndarray,
signal_type: str = "breathing") -> np.ndarray:
"""
自适应卡尔曼滤波

Args:
signal: 输入信号
signal_type: "breathing" or "heartbeat"

Returns:
filtered_signal: 滤波后的信号
"""
if signal_type == "breathing":
Q = self.Q_breath
R = self.R_breath
else:
Q = self.Q_heart
R = self.R_heart

N = len(signal)

# 初始化
x_estimate = signal[0]
P_estimate = 1.0

filtered_signal = np.zeros(N)

for i in range(N):
# 预测
x_predict = x_estimate
P_predict = P_estimate + Q

# 更新
K = P_predict / (P_predict + R)
x_estimate = x_predict + K * (signal[i] - x_predict)
P_estimate = (1 - K) * P_predict

filtered_signal[i] = x_estimate

# 自适应调整R(观测噪声)
if i > 10:
# 根据残差调整R
residual = abs(signal[i] - x_predict)
R = 0.9 * R + 0.1 * residual ** 2

return filtered_signal

def square_root_normalization(self,
signal: np.ndarray) -> np.ndarray:
"""
平方根归一化

消除呼吸谐波对心跳的影响

Args:
signal: 输入信号

Returns:
normalized: 归一化后的信号
"""
# 计算平方根
sqrt_signal = np.sqrt(np.abs(signal))

# 归一化
normalized = (sqrt_signal - np.mean(sqrt_signal)) / (np.std(sqrt_signal) + 1e-6)

return normalized

def extract_vital_signs(self,
phase_signal: np.ndarray) -> dict:
"""
完整生命体征提取流程

Args:
phase_signal: 相位信号

Returns:
dict: {
"breathing_rate": float, # bpm
"heart_rate": float, # bpm
"breathing_signal": np.ndarray,
"heart_signal": np.ndarray
}
"""
# 1. 相位差分消除静态杂波
phase_diff = self.phase_differencing(phase_signal)

# 2. 平方根归一化(消除呼吸谐波)
normalized = self.square_root_normalization(phase_diff)

# 3. 自适应卡尔曼滤波 - 呼吸
breathing_signal = self.adaptive_kalman_filter(
normalized, "breathing"
)

# 4. 自适应卡尔曼滤波 - 心跳
heart_signal = self.adaptive_kalman_filter(
normalized, "heartbeat"
)

# 5. 频谱分析提取频率
breathing_rate = self._extract_frequency(breathing_signal, self.breathing_range)
heart_rate = self._extract_frequency(heart_signal, self.heartbeat_range)

return {
"breathing_rate": breathing_rate,
"heart_rate": heart_rate,
"breathing_signal": breathing_signal,
"heart_signal": heart_signal
}

def _extract_frequency(self,
signal: np.ndarray,
freq_range: Tuple[float, float]) -> float:
"""从信号中提取主频率"""
from scipy.fft import fft, fftfreq

N = len(signal)

# FFT
spectrum = np.abs(fft(signal))[:N//2]
freq = fftfreq(N, 1/self.fs)[:N//2]

# 在目标频率范围内搜索峰值
mask = (freq >= freq_range[0]) & (freq <= freq_range[1])

if np.sum(mask) == 0:
return 0.0

peak_idx = np.argmax(spectrum[mask])
peak_freq = freq[mask][peak_idx]

# Hz → bpm
rate = peak_freq * 60

return rate


# 测试示例
if __name__ == "__main__":
extractor = AdaptiveKalmanVitalSigns(fs=20.0)

# 模拟相位信号(呼吸 + 心跳)
t = np.arange(0, 30, 1/20.0) # 30秒

breathing_signal = 0.5 * np.sin(2 * np.pi * 0.25 * t) # 15 bpm
heart_signal = 0.1 * np.sin(2 * np.pi * 1.2 * t) # 72 bpm
noise = 0.05 * np.random.randn(len(t))

phase_signal = breathing_signal + heart_signal + noise

# 提取生命体征
result = extractor.extract_vital_signs(phase_signal)

print("=== 生命体征检测结果 ===")
print(f"呼吸频率: {result['breathing_rate']:.1f} bpm")
print(f"心跳频率: {result['heart_rate']:.1f} bpm")
print(f"呼吸信号长度: {len(result['breathing_signal'])}")
print(f"心跳信号长度: {len(result['heart_signal'])}")

性能评估(论文数据)

指标 传统FFT 传统卡尔曼 自适应卡尔曼
呼吸检测精度 92% 94% 98%
心跳检测精度 75% 82% 91%
静态杂波抑制 70% 85% 95%
谐波消除 60% 70% 88%

Euro NCAP CPD应用

应用场景 自适应卡尔曼优势
儿童呼吸检测 高精度呼吸频率提取
心跳监测 消除呼吸谐波干扰
多目标分离 每个目标独立滤波
静止儿童检测 微弱信号增强

参考资料

  1. Nature Scientific Reports 2025
  2. Adaptive Kalman Filtering for Vital Signs
  3. Euro NCAP 2026 CPD Protocol

总结

自适应卡尔曼核心:

  1. 相位差分:消除静态杂波
  2. 平方根归一化:消除呼吸谐波
  3. 自适应调整:根据残差更新噪声参数

IMS开发优先级:

  • 🔴 高:自适应卡尔曼滤波实现
  • 🟡 中:多bin信号叠加增强
  • 🟢 低:平方根归一化优化

下一步行动:

  • 实现AdaptiveKalmanVitalSigns类
  • 测试TI AWRL6844数据
  • 对齐Euro NCAP CPD生命体征检测场景

Nature 2025:毫米波雷达生命体征检测自适应卡尔曼滤波框架
https://dapalm.com/2026/07/09/2026-07-09-adaptive-kalman-mmwave-vital-signs-nature-2025/
作者
Mars
发布于
2026年7月9日
许可协议