在这里插入图片描述

——从毫米波雷达数据到呼吸曲线

如果你第一次接触毫米波雷达的生命体征检测,很可能会觉得这件事有点神奇。

一个人坐在椅子上几乎没有明显动作,
雷达却能够检测到他的呼吸。

很多人会下意识地认为,这背后一定依赖某种复杂的 AI 算法。但真实情况恰恰相反。

在绝大多数雷达系统中,呼吸检测算法其实非常“朴素”。
核心思想可以概括为一句话:

观察人体胸腔的微小周期运动。

只要雷达系统具有足够好的距离分辨率和相位稳定性,这种毫米级的微小位移就会反映在回波信号的相位变化中。

换句话说,雷达并不是直接“看到”胸腔在运动,而是通过信号中的相位变化推断出这种运动。

在这篇文章中,我们做一件非常具体的事情:

用 Python 写一个简单的呼吸检测算法,从原始雷达数据中恢复出一条呼吸曲线。

整套流程适用于 RS6013A 毫米波雷达实验套件 等能够输出原始 ADC 数据的系统。


一、呼吸检测的物理原理

在开始写代码之前,我们先从物理原理出发,理解雷达是如何感知呼吸的。

假设一个人坐在雷达前方 1 米左右 的位置,保持安静呼吸。

当人体呼吸时,胸腔会产生前后往复的运动,典型位移范围大约是:

几毫米到一厘米。

对于人来说,这样的位移几乎感觉不到,但对于毫米波雷达来说,这已经是一个相当明显的变化。

原因在于毫米波的波长非常短。

以常见的 77 GHz 毫米波雷达 为例,其波长大约为:

λ ≈ 3.9 mm

当胸腔移动 1 mm 时,回波信号的相位就会产生明显变化。

换句话说:

雷达并不是“看见胸腔”,
而是“看见相位在周期变化”。

只要把这种周期变化提取出来,就能得到呼吸信号。
在这里插入图片描述
在这里插入图片描述

图中示意了毫米波雷达检测呼吸的基本原理:
人体胸腔在呼吸过程中产生毫米级位移,这种微小运动会引起回波信号相位的周期变化。


二、相位变化与位移的数学关系

从数学角度来看,雷达检测呼吸的原理其实非常清晰。

当雷达接收到人体反射的电磁波时,回波信号可以表示为:

s(t)=Aejϕ s(t) = A e^{j\phi} s(t)=Aejϕ
其中:

  • (AAA) 表示信号幅度
  • (ϕ)(\phi)(ϕ) 表示信号相位

对于距离为 ® 的目标,其相位为:

ϕ=4πRλ \phi = \frac{4\pi R}{\lambda} ϕ=λ4πR​
这里:

  • (RRR) 为目标距离
  • (λ\lambdaλ) 为雷达波长

当人体呼吸时,胸腔会产生微小位移 (\Delta R)。

此时相位变化为:

Δϕ=4πΔRλ \Delta \phi = \frac{4\pi \Delta R}{\lambda} Δϕ=λ4πΔR​
这条公式非常关键,它说明:

毫米级位移会转化为明显的相位变化。

举一个简单例子。

对于 77 GHz 雷达:

λ≈3.9mm \lambda \approx 3.9 mm λ≈3.9mm
如果胸腔移动 1 mm:

Δϕ≈3.2rad \Delta\phi \approx 3.2 rad Δϕ≈3.2rad
这已经是一个非常明显的相位变化。

因此,通过连续观测相位随时间变化,就可以恢复出人体的呼吸节律。


三、呼吸检测的基本流程

从雷达数据到呼吸曲线,大致需要经过几个步骤。

首先,雷达持续发射 FMCW chirp 并采集 ADC 数据。
通过 Range FFT,可以得到每一帧的距离谱。

接下来,在距离谱中找到人体所在的 range bin。

人体所在的距离单元会随着呼吸产生微小相位变化。

然后提取这个 range bin 在连续帧中的相位变化。

最后,通过带通滤波去除噪声,就可以得到稳定的呼吸曲线。

整体流程如下:

ADC数据
   ↓
Range FFT
   ↓
定位人体所在距离bin
   ↓
提取相位变化
   ↓
带通滤波
   ↓
呼吸信号

在这里插入图片描述


四、Python 实现呼吸检测

假设我们已经从雷达系统获取一段数据:

radar_data.shape = [num_frames , num_samples]

代码如下:

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import butter, filtfilt

# 加载雷达数据
data = np.load("radar_adc.npy")

num_frames, num_samples = data.shape

# Range FFT
range_fft = np.fft.fft(data, axis=1)

# 找到能量最大的距离bin(假设为人体)
range_bin = np.argmax(np.mean(np.abs(range_fft), axis=0))

# 提取该距离bin信号
signal = range_fft[:, range_bin]

# 相位
phase = np.angle(signal)

# 相位展开
phase = np.unwrap(phase)

# 呼吸频率范围
fs = 20
low = 0.1
high = 0.5

b, a = butter(2, [low/fs*2, high/fs*2], btype='bandpass')
breath = filtfilt(b, a, phase)

plt.figure(figsize=(8,4))
plt.plot(breath)
plt.title("Breathing Signal")
plt.xlabel("Frame")
plt.ylabel("Amplitude")
plt.show()

运行之后,你会得到一条比较平滑的曲线。

这条曲线的周期,就是人的呼吸周期。


五、MATLAB 版本实现

如果你使用 MATLAB,代码实现也非常直观:

load radar_adc.mat

[numFrames, numSamples] = size(data);

range_fft = fft(data, [], 2);

power = mean(abs(range_fft),1);
[~,range_bin] = max(power);

signal = range_fft(:,range_bin);

phase = angle(signal);
phase = unwrap(phase);

fs = 20;

[b,a] = butter(2,[0.1 0.5]/(fs/2),'bandpass');

breath = filtfilt(b,a,phase);

plot(breath)
title('Breathing Signal')
xlabel('Frame')
ylabel('Amplitude')

两种实现思路完全一致,只是语法不同。


六、运行结果示意

当算法正常工作时,你会看到类似下面这样的呼吸波形。
在这里插入图片描述
在这里插入图片描述

曲线大约每 3~5 秒 出现一个周期。

换算为呼吸频率,大概是:

12 ~ 20 次 / 分钟

这正是人体正常呼吸范围。


七、为什么毫米波雷达适合做呼吸检测

相比传统传感器,毫米波雷达有几个天然优势。

首先,它是 非接触式检测技术。
人不需要佩戴设备,只需坐在雷达前方即可检测。

其次,它 不受光照影响。
在完全黑暗环境下也可以工作。

更重要的是,毫米波雷达对 毫米级位移极其敏感。

因此,近年来很多研究和产品开始使用毫米波雷达进行:

  • 呼吸检测
  • 心跳检测
  • 睡眠监测
  • 老人跌倒检测
  • 智能家居感知

八、从“能检测”到“好用”,还有很多工程细节

上面这套算法虽然简单,但真实系统中还会遇到很多问题,例如:

人体不止一个人时怎么办?
人轻微移动怎么办?
呼吸和心跳如何分离?

工程上通常会加入:

  • 背景静态去除
  • Range bin 跟踪
  • 自适应滤波
  • 多目标分离

很多时候,这些工程细节反而比基础算法更复杂。


九、写在最后

很多人第一次看到毫米波雷达呼吸检测时都会觉得:

这是不是某种“黑科技”。

但当你把整个链路拆开,会发现它其实非常朴素:

雷达只是非常擅长观察 微小位移。

当这种位移是周期性的,就变成了呼吸信号。

从 ADC 数据 到 Range FFT,再到 相位变化,这条信号处理链路其实非常优雅。

如果你手里有 RS6013A 毫米波雷达实验套件,完全可以自己试一遍。

第一次看到真实呼吸曲线的时候,你会有一种很特别的感觉:

雷达不仅在“看世界”,
它甚至在“听见生命”。

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐