1. 项目目标与整体设计思路
1.1 为什么用FMCW雷达做人体行为识别
这两年做养老监护、智能家居的项目越来越多,摄像头方案遇到的最大瓶颈不是算法,而是隐私——卫生间、卧室这种场景根本没法装摄像头,甲方一听就摇头。雷达方案天然规避这个问题:它只输出目标的距离、速度、角度信息,没有人脸、没有肢体图像,数据本身是“非视觉”的,却能捕捉到足够丰富的运动特征。
FMCW(调频连续波)雷达是其中用得最多的一类。相比脉冲雷达,FMCW体制结构简单、成本低、分辨率高,尤其适合近距离的人体感知。一颗77GHz的毫米波雷达芯片,价格已经能做到几十块钱量级,探测距离从0.5米到十几米,距离分辨率能做到厘米级,测速精度在0.05m/s左右,完全覆盖人体日常动作的速度范围。
本文要解决的问题很直接:很多团队卡在“有雷达却不不知道数据怎么组织成数据集”这一步——原始ADC数据是复数矩阵,看着像噪声,不知道该怎么变成能喂给CNN的图像。我基于自己做过的真实项目,完整走一遍从FMCW雷达数据采集、信号处理、RD谱图生成到6类动作数据集标注的全流程,行走、跌倒、喝水、坐下起立、挥手、静止,每类动作的采集规范和避坑点都会讲到。适合正在做雷达感知入门、准备搭建自有数据集、或者想用雷达替代视觉做人行为识别的工程师参考。
1.2 数据处理链路总览
整套流程可以用一句话概括:把时间维的雷达回波,通过两次FFT变成距离-多普勒谱(RD谱),再把RD谱转成灰度图,让视觉领域的CNN、ResNet这些成熟模型直接来处理。
这样做的核心原因是工程上的复用:视觉分类模型已经非常成熟,预训练权重、部署工具链、优化经验全都现成。如果自己从雷达原始信号直接设计模型,不仅周期长,调参经验也少。把信号转成图,等于把问题从“雷达信号处理”转化成了“图像分类”,难度骤降。
完整链路如下:
- 雷达发射线性调频脉冲,接收回波,经混频得到中频IF信号
- ADC采样,得到原始数据矩阵,一帧内包含多个chirp的采样点
- 对每个chirp做距离维FFT,得到目标的距离信息
- 对慢时间维做多普勒FFT,得到目标的速度信息
- 取幅度谱,做静态杂波抑制(MTI)、对数压缩、归一化
- 将RD谱保存为灰度图,同时生成距离-时间图(RT图)和多普勒-时间图(DT图)
- 为每帧数据打标签,按动作类别组织成标准数据集
整个过程完全不涉及深度学习的训练,但每一个环节都直接影响最终模型的准确率。数据集的构建质量,决定了模型上限——后面模型调得再好,也弥补不了数据集本身的缺陷。
2. 实验环境搭建与雷达参数计算
2.1 硬件选型建议
我实验用的是TI(德州仪器)的IWR1443BOOST评估板配合DCA1000EVM数据采集卡,这套组合在雷达数据集构建的圈子里用得最广泛,几乎成了事实标准。IWR1443内置3发4收天线阵列,工作频段76-81GHz,最大带宽4GHz,足以支撑厘米级距离分辨率。
如果预算有限,也可以用IWR6843ISK(60GHz频段)或者AWR1843BOOST。IWR1443的最大优势是资料全、例程多,TI官方mmWave Studio软件可以直接拖拽配置参数并导出ADC原始数据。DCA1000EVM负责把雷达的LVDS数据转成以太网数据,传输到PC端做后续处理,这一点很关键——如果没有DCA1000,IWR1443只能输出处理后的点云信息,拿不到原始ADC数据,就无法自己做RD谱图,所以要采原始数据,DCA1000基本是标配。
下表是我实测过的几套配置对比:
| 硬件组合 | 频段 | 原始ADC输出能力 | 适用场景 | 参考价格 |
|---|---|---|---|---|
| IWR1443 + DCA1000 | 77GHz | 支持 | 测距测速、RD谱、微多普勒 | 较高 |
| IWR6843 + DCA1000 | 60GHz | 支持 | 人体感知、生命体征、动作识别 | 中等 |
| AWR1843 + DCA1000 | 77GHz | 支持 | 车载、多目标跟踪 | 较高 |
| 24GHz模块(如BGT24LTR11) | 24GHz | 不支持 | 简易存在检测,难做RD谱 | 低 |
给新手的建议是:直接上IWR1443 + DCA1000,一次到位。24GHz模块虽然便宜,但带宽有限,距离分辨率只能做到0.75米左右,连区分人的手臂和躯干都费劲,做动作识别基本没戏。
2.2 FMCW关键参数计算
FMCW雷达的参数配置是数据质量的地基。我先写一遍完整推导,每一步都能代入实际数值,照着算就行。
FMCW雷达通过发射频率线性变化的信号,把目标的距离信息映射到中频频率上。发射信号频率随时间线性上升,上升斜率S(chirp斜率)的单位是Hz/s。回波信号经过一段传输延迟τ=2R/c(R为目标距离,c为光速)后,与当前发射信号混频,得到的中频频率为:
f_IF = S × τ = S × 2R / c
所以只要测出中频频率,就能反推距离。而实际测量中,我们用ADC对中频信号采样,再做FFT得到频率。FFT的频率分辨率是1/T(T为采样窗口时长),因此距离分辨率由带宽决定:
ΔR = c / (2 × B)
B为线性调频的总带宽。IWR1443最大带宽4GHz,理论上ΔR = 3e8 / (2 × 4e9) = 3.75cm。这个分辨率足以分辨人的躯干、手臂等不同部位的回波。
最大不模糊距离方面,受ADC采样率限制。中频信号是实信号,FFT后正负频率对称,实际可用带宽为Fs/2,因此:
R_max = c × Fs / (2 × S × 2) = c × Fs / (4 × S)
最大速度的计算同样重要。人体动作尤其是跌倒,瞬时速度可以到2-3m/s,多普勒频率随之升高。速度维FFT是在多个chirp之间做的,受脉冲重复频率(PRF,即chirp周期Tc的倒数)限制:
v_max = λ / (4 × Tc)
λ为雷达工作波长,77GHz对应的波长λ = c / f = 3e8 / 77e9 ≈ 3.9mm。
我实际使用的参数组合如下:
| 参数 | 数值 | 说明 |
|---|---|---|
| 起始频率 | 77GHz | IWR1443默认频段 |
| 调频带宽B | 4GHz | 理论距离分辨率3.75cm |
| chirp斜升S | 29.982MHz/μs | mmWaveStudio自动计算 |
| ADC采样率Fs | 10MHz | 受限于中频带宽 |
| 每个chirp采样点数N | 256 | 距离FFT点数 |
| 每帧chirp数M | 128 | 速度FFT点数 |
| chirp周期Tc | 80μs | PRF=12.5kHz |
| 帧周期Tf | 40ms | 帧率25fps |
| 目标距离范围 | 0.5-6m | 室内场景 |
按这个配置,每个chirp的采样时长为256/10MHz = 25.6μs,chirp剩余时间做调频回扫和空闲等待。最大不模糊距离用公式R_max = c × Fs / (2S) 估算,Fs=10MHz、S=29.982MHz/μs时:
R_max = 3e8 × 10e6 / (2 × 29.982e12) ≈ 50m
实际室内场景远用不到这么远,但高余量可以避免近距离强反射造成折叠。
速度分辨率由帧周期决定:
Δv = λ / (2 × Tf) = 3.9e-3 / (2 × 40e-3) ≈ 0.049m/s
也就是约5cm/s的速度分辨率。人体慢速动作的手部移动大约在0.1-0.5m/s,完全在分辨能力之内。最大不模糊速度:
v_max = λ / (4 × Tc) = 3.9e-3 / (4 × 80e-6) ≈ 12.2m/s
这个量级已经超过了跌倒时身体下坠的最大速度,不会出现多普勒模糊。很多新手直接用官方默认配置,没有根据动作速度去验证v_max是否够用——这是一个很隐蔽的坑,后面我会专门讲。
2.3 数据采集软件链路
TI的mmWaveStudio是最常用的采集软件,操作流程如下:
- 连接IWR1443 + DCA1000,在设备管理器中确认端口
- 打开mmWaveStudio,加载IWR1443的配置文件(.cfg),设置上述参数
- 连接雷达并发送配置,确认状态栏显示Sensor started
- 在DCA1000配置页设置以太网目标IP(PC端IP需与DCA1000在同一网段,通常为192.168.33.30)
- 开启采集后,设置单帧采集次数或连续采集模式
- 停止采集,导出为bin文件,每帧数据按固定的字节顺序排列
mmWaveStudio导出的原始数据格式是复数IQ交替存储,即两个uint16字节表示一个复数点(I实数部分和Q虚数部分)。单帧原始数据量为:256(采样点)× 128(chirp数)× 4通道(1路Tx工作)× 2(I/Q) × 2字节 = 512KB。按25fps计算,每秒产生12.8MB数据,采10分钟就是7.7GB。所以采集之前要算好硬盘空间。
我自己会用Python写一个采集控制脚本,通过TCP指令控制mmWaveStudio的采集开始和停止,同时记录动作编号和志愿者信息,这样后期不用人工去对应文件名和动作类别。这个细节看起来小,但素材多了以后非常省事。
3. 数据采集流程与动作规范设计
3.1 采集场景布置
雷达安装位置直接影响数据分布。我实验的场地是一间约4m × 5m的室内房间,雷达架设在三脚架上,离地高度1.2m(大致与人体胸口齐平),雷达面板朝向正对活动区域,略有5-10°的下倾角以便覆盖跌倒后的躺倒区域。
雷达与动作区域的距离控制在1-3m。太近(小于0.5m)会导致目标在距离维上跨越多个距离门,RD谱上能量分散;太远(大于5m)时人体雷达截面积变小,信噪比明显下降。场地内移开所有可移动金属物体(椅子、金属水杯、手机支架),因为这些物体反射远强于人体,会把弱小的人体回波压制下去。
每个志愿者动作前,先采集一段5秒的空场景数据(没有人),后期用这一段计算静态杂波基底。这一步很多人忽略,认为信号处理里的MTI能搞定一切,但实际环境中雷达自身的热漂移、天线串扰噪声都会随温度变化,空场景基线可以帮助后期做更干净的背景对消。
3.2 六类动作的行为定义与采集脚本
行为识别数据集最关键的是动作定义要清晰,不然标注阶段一定扯皮。我根据实际应用场景,把动作定义为以下六类:
0_walk(行走):志愿者以正常步速(约1-1.5m/s)从雷达视场一侧走到另一侧,包括横向穿过、斜向接近再远离两种路径。每次记录3秒,覆盖整个行走过程。
1_fall(跌倒):这是整个数据集里最难采也最重要的一类。志愿者从站立姿态,在雷达视场内向前、向后、侧向三个方向倒地。为安全起见地上铺垫了5cm厚的软垫,但要注意软垫不能太大,否则会产生强多径反射干扰RD谱。每次记录从开始前倾到完全倒地静止后的2秒,共约5秒。
2_drink(喝水):志愿者站在雷达前方约1.5m处的小桌旁,从桌面拿起水杯,举到嘴边喝水,喝一口后放回桌面。这个动作的特点是全身基本不动,只有手臂做小范围运动,多普勒频移小,是六个类别里最难识别一类。
3_sit_stand(坐下起立):从站立姿势走向椅子,转身坐下,静坐2秒,再站起。这个动作包含剧烈的快速下坠段和静止段,和跌倒的动作模式有些相似,但与跌倒的重要区别是幅度不同且结束后回到站立状态。
4_wave(挥手):站在雷达前方1-2m,原地单臂或双臂前后摆动、上下挥动,幅度由慢到快,每个样本记录3秒。这一类的目的是采集大幅度的周期运动模式。
5_still(静止):站在或坐在雷达视场内,保持静止状态,呼吸自然。人体即使静止,胸腔的起伏也会引起微弱的多普勒调制,采集这种底噪数据有助于模型在分类时不会把所有“有能量”的信号都当动作。
每类动作的样本规划:
| 动作类别 | 每人次数 | 所需人员 | 单次时长 | 样本量 |
|---|---|---|---|---|
| walk | 30 | 8人 | 3s | 240 |
| fall | 15 | 8人 | 5s | 120 |
| drink | 30 | 8人 | 5s | 240 |
| sit_stand | 30 | 8人 | 5s | 240 |
| wave | 30 | 8人 | 3s | 240 |
| still | 30 | 8人 | 3s | 240 |
跌倒由于采集难度大、体力消耗大,样本量减半,这个不平衡通过后期扩增和数据增强来补。我找的8名志愿者身高从158cm到185cm、体型各异,年龄跨度20-40岁,保证数据集有一定的个体差异。建议你也这样找,别只拿自己和同事凑数——模型很容易过拟合到某个特定身高体型的雷达截面积特征上。
3.3 采集过程中的质量控制
采集不是录完就完事,每个样本采集完要立刻做初步检查。我在采集时定了三个快速判断标准:
一是原始数据幅度是否饱和。ADC输出的数据范围是0-4095(12位),如果中频信号过大,波形顶部削平,FFT之后会在频谱上出现大量虚假谐波。这个在mmWaveStudio的时间域波形窗口里可以直观看到。
二是目标信号是否落在有效距离门内。实时处理一帧数据,观察RD谱上是否有明显峰值出现在1-3m的范围内。如果峰值不在,很可能是参数配置错误或者雷达前方有遮挡。
三是背景底噪是否过高。雷达开机后取一帧全空场景数据的平均幅度,如果底噪高于-40dBm(对应ADC码值波动超过几十),说明环境电磁干扰严重或者天线连接异常,需要排查后重采。
我自己会在每个动作批次结束后,用脚本把所有原始文件做一次FFT批量检查,生成一张包含距离-多普勒最大值的质量报告图。20分钟能检查完一个批次的150个文件。这个步骤能避免采集完两小时才发现设备配置有问题、所有数据作废的情况。
4. 雷达信号处理与图片生成
4.1 距离维FFT:从时域回波到距离分布
雷达原始数据读取后,第一个操作是对每个chirp的采样点做FFT。我们把原始bin文件按帧组织成维度为(chirp数M,采样点数N,通道数C)的复数矩阵。对采样点维做FFT,得到一个chirp内不同距离门上的能量分布。
以N=256为例,FFT后的每一个索引n对应的距离可以这样计算:距离FFT的分辨率ΔR = c/(2B) = 3.75cm,做FFT后第n个距离门对应的物理距离是n × ΔR,范围从0到N × ΔR = 9.6m。实际处理时通常去掉最前面的几个距离门(天线耦合区,一般最近的0.1m内有强干扰),只保留0.5m到6m的范围。
这里要强调开窗的重要性。直接做256点FFT,不加窗的话,频谱泄漏会把弱信号淹没在强信号旁瓣里。我用的是一维汉明窗(hamming),加在采样点维上。汉明窗的主瓣稍宽(约为矩形窗的1.5倍),但旁瓣衰减能做到-43dB,能够有效抑制近距离强反射体(比如墙壁)的旁瓣掩盖。
加窗会造成有效距离分辨率下降,这是可以接受的,因为人体行为识别不需要每个距离门都达到理论的3.75cm分辨率,有6-8cm的有效分辨率完全够。
4.2 多普勒维FFT:从距离分布到运动速度
距离FFT完成之后,我们得到的是一个“距离-慢时间”矩阵,每一列是特定距离门在不同chirp时刻的复数值。要对慢时间维(即chirp索引维)再做一次FFT,才能得到多普勒频率,也就是目标的速度信息。
多普勒FFT的点数等于每帧的chirp数M=128。FFT后每个频点代表一个速度。速度分辨率Δv ≈ 0.05m/s(前文已算),正频率表示目标靠近雷达,负频率表示远离。这样每一帧就得到一个128 × 256的复数RD谱,取幅度后,就是我们常说的RD图。
但这里有个细节:人体不是刚性目标。人走路时,躯干以约1m/s的速度移动,同时手臂以不同的速度摆动,跌倒时更是全身多个部位同时以不同速度运动。RD谱上不会只有一个单一峰,而是一大片速度-距离分布的能量团。这正是基于雷达做行为识别的核心优势——RD谱天然包含运动目标各个散射点的速度-距离分布,信息密度远高于摄像头输出的单一的bbox。
RD谱的幅度值动态范围很大,强反射点(如人体躯干)和弱反射点(如精细的手部运动)可能相差40dB以上。直接线性保存会导致弱信号在后续量化到8位灰度图时完全丢失。处理办法是取对数幅度:
I_dB = 20 × log10(|RD| + ε)
然后再做归一化。ε取一个小数(如1e-6)防止log10(0)出现。
4.3 静态杂波抑制与CFAR检测
室内环境最大的干扰源是墙壁、桌椅等静止物体的反射。虽然在距离FFT后这些反射固定在某个距离门不变,但其强度往往是人体回波的几十倍。不处理的话,RD谱上人体的动态变化会被静态杂波完全淹没——尤其是喝水这类小幅度运动,与静态背景相比微不足道。
最有效的处理是MTI(动目标显示),本质上就是一个两脉冲对消器。对同一距离门的慢时间序列做一阶差分:
y[n] = x[n] - x[n-1]
x[n]是第n个chirp在该距离门的复数值。静止物体的多普勒频率为0,慢时间维不变,对消后输出为0;运动目标信号随chirp变化,差分后被保留。MTI之后的RD谱再做多普勒FFT,静态分量就被彻底去除了。
实际效果对比很明显:未做MTI时,RD谱上在距离0.8m处有一条亮度极高的墙反射水平线,人体信号在它旁边几乎不可见。做了一阶对消后,墙体线消失,人体运动的RD谱形态清晰可见。
CFAR(恒虚警率检测)本期内容用得不多,但可以作为自动提取目标区域的工具。我用CA-CFAR在RD谱上逐距离门计算背景噪声功率,设定虚警率Pfa=1e-4,自适应提取出超过阈值的点目标区域,再以这些点的边界生成一个注意力掩膜。这样可以自动裁剪掉无目标的背景区域,减少图片中的无效信息。
CFAR的核心思想是每个检测单元的背景噪声水平用周围参考单元的均值来估计,保护单元隔开目标本身的影响。参考单元取8-12个,保护单元4-6个,窗口太大拖慢处理,太小则背景估计不稳定。我实测128×128的RD谱,用numpy向量化实现,单帧CFAR不到1ms,相当快。
4.4 从RD谱到图片的三种生成方案
有了干净的RD谱,接下来就是把数据组织成图片。三种方案我都试过,根据任务需求灵活选用:
方案A:单帧RD灰度图。将一帧128×128的RD幅度谱做log压缩后,缩放到0-255,保存为灰度PNG。优点是实现最简单、每张图独立,适合直接用现成的图像分类模型。缺点是丢失了时间上下文——单帧只能看到“这一刻哪些距离处在发生多少速度的运动”,对于喝水这种连续动作,单帧图的特征不够明显。
方案B:多帧RD图级联。取连续K帧(我常用的K=8,约0.32秒)的RD谱,沿通道维堆叠后保存成“假彩色”三通道图。第一通道放当前帧,第二通道放过去第4帧,第三通道放过去第8帧。8帧的时间跨度为0.32秒,正好能覆盖一个动作的短时发展过程。模型可以同时从图像内容(距离-速度关系)和通道差异(时间演化)中提取特征。
方案C:RT图与DT图。分别对RD谱的某个维度做积累/投影,生成距离-时间图(RT图)和多普勒-时间图(DT图)。RT图的横轴是时间,纵轴是距离门,像素亮度表示目标在该时间该距离处的能量。跌倒检测用RT图特别直观——身体快速下坠时,RT图上呈现一条快速下降的亮线,然后转为水平静止线。
我最终采用方案B作为主要数据集格式,同时保留方案A的RD图和方案C的RT图作为辅助通道。这样模型可以从三个维度感知动作,实测下来比单一特征图精度高5-10个点。如果你第一次做,建议先做方案A打通流程,再逐步加B和C。
5. 标签标注与数据集组织
5.1 数据清洗与有效片段截取
每段原始录像不仅有目标动作,还有动作前后的准备时间。比如跌倒样本里包含了站立、准备、倒地、静止四个阶段,如果整段3-5秒都标注为“跌倒”,模型学到的特征会掺入大量静止状态,影响分类效果。
我采用的方法是半自动截取:对每段原始回放数据,先计算每一帧RD谱的总能量E(t) = sum(|RD(t)|^2),然后看能量曲线。动作发生时能量会有一个明显的脉冲式上升,静止时能量落在低水平。用滑动窗口找能量超过背景均值3dB以上且持续时间超过0.5秒的区间,作为候选动作段。
候选区间还需要人工确认。这里有一个容易犯的错:不能只看RD谱总能量。喝水动作的体动幅度小,总能量变化不明显,但如果监测特定距离门(比如手臂所在的距离门),能量变化会清晰很多。我写了一个辅助标注脚本,能同时显示RT图和总能量曲线,拖动滑条逐帧查看,人工确认每个动作段的起止帧。
5.2 标注格式与目录组织
数据集的目录结构我设计如下:
dataset/ ├── raw/ # 原始bin文件,按人员分组 │ ├── subject_01/ │ │ ├── walk/ │ │ │ ├── 0001_20240110.bin │ │ └── ... ├── images/ # RD谱图,按类别分组 │ ├── train/ │ │ ├── walk/ │ │ ├── fall/ │ │ ├── drink/ │ │ ├── sit_stand/ │ │ ├── wave/ │ │ └── still/ │ ├── val/ │ └── test/ ├── labels/ │ ├── annotations.json # 每帧标注 │ └── dataset_info.json # 元信息 ├── train.txt # 训练集文件列表 ├── val.txt # 验证集文件列表 ├── test.txt # 测试集文件列表 └── tools/ # 数据生成与检查脚本标注文件annotations.json的格式如下:
{ "sample_id": "subject_01_walk_0001", "class_id": 0, "class_name": "walk", "subject_id": "subject_01", "start_frame": 10, "end_frame": 80, "num_frames": 71, "radar_config": { "start_freq": 77e9, "bandwidth": 4e9, "adc_fs": 10e6, "num_chirps": 128, "samples_per_chirp": 256, "frame_rate": 25 } }数据集关键变量记录在dataset_info.json里,包括雷达参数、房间大小、雷达高度、志愿者信息脱敏编号、采集日期、环境温湿度。记录雷达参数很重要——不同参数配置下采集的数据不能直接混用,后期如果换雷达或者改配置,最好单独维护版本。
5.3 训练集/验证集/测试集划分规则
划分策略直接影响模型评估的可靠性。最错误的方式是随机打乱所有帧再划分,因为同一动作片段的相邻帧高度相似,随机划分会把强相关数据同时塞进训练集和测试集,导致测试准确率虚高。
正确的做法是按志愿者划分:把8名志愿者的数据按6:1:1划分到train/val/test,确保测试集中的志愿者身份完全没有出现在训练集中。这种划分更能反映模型面对新个体的泛化能力,也更贴近真实部署场景。
我实测过这种划分下模型的准确率会比随机划分低8-12个百分点,这是正常现象,不要被这个数字吓到。真实场景中模型遇到的一定是没见过的陌生人,这种严格划分才是有意义的评估标准。
数据不平衡的问题可以通过加权采样缓解。跌倒样本量最少,我在构建DataLoader时给跌倒类别乘以较大的采样权重(如每批中强制包含20%的跌倒样本),实测比简单的过采样效果好,不容易过拟合到重复样本。
5.4 数据增强策略
雷达图像数据的增强方式与常规图像有些不同。水平翻转不能随便用——RD谱的左右方向分别对应靠近和远离雷达,翻转后语义完全变了。可以做且有效的增强包括:
- 噪声扰动:在RD谱上叠加高斯白噪声,模拟不同信噪比环境
- 幅度缩放:小幅调整全局增益,模拟距离变化
- 时间裁剪:从完整动作序列中随机截取固定长度的段
- 混合增强(Mixup):两张不同类别的RD图按比例融合,标签也按对应比例混合
- 随机擦除:随机遮盖图中一小块区域,强制模型学习全局特征而不是只靠局部强反射点
这些增强手段全部在数据加载时在线完成,不会增加磁盘存储压力。增强后的数据量,相当于把原始样本扩大了20倍都不止。
6. 实操中的坑与排查技巧
6.1 多普勒模糊与速度混叠
我踩过最深的坑是多普勒模糊。第一次实验时我为了省采集时间,把chirp周期Tc设成了200μs,结果测人体快速挥手时,RD谱上出现了折叠回绕的虚假速度分量。回看计算:v_max = λ/(4Tc) = 3.9e-3/(4 × 200e-6) ≈ 4.88m/s。挥手末端速度如果到5m/s以上,真实速度超过最大不模糊速度,就会折返到反向速度区间,RD谱上一片混乱。
排查方法很简单:先采集一个已知运动速度的标定目标(比如用角反射器装在已知转速的电机转盘上),对比实测多普勒频率和理论值。如果实测值出现反向或跳变,基本可以判断是多普勒模糊。
解决办法是缩短chirp周期Tc,提高到80μs,使v_max达到12.2m/s,覆盖人体所有动作的速度范围。代价是每个chirp的采样时间被压缩,中频频率略高,但信噪比仍然足够。
6.2 多径反射与虚假目标的干扰
室内多径效应在实际采集时不可避免。雷达信号打到地面、墙壁再反射到人体,会形成额外路径,在RD谱上表现为虚假的距离速度分量。尤其是跌倒动作,身体贴近地面时,地面反射路径与直达路径干涉,RD谱上的能量分布会变得非常复杂。
处理思路有三个方向。一是物理手段:在动作区域地面铺吸波材料(泡沫板或吸波海绵),减弱镜面反射。二是算法手段:利用到达角度(AoA)估计区分直达路径和多径路径,这需要多天线支持,IWR1443的4天线可以做到。三是数据手段:采集时加入多个角度、多个位置的动作数据,让模型学会在存在多径的情况下依然提取动作特征。
我之前没有处理多径,直接训练模型,发现跌倒的识别准确率明显低于其他动作,误报大多是坐在椅子上的静止人员被识别成跌倒。后来在采集阶段增加了地面吸波材料,误报率下降了一半左右。这个教训值得记住:雷达数据集的采集,环境物理特性对模型的影响超过了后期任何调参技巧。
6.3 数据对齐与时间戳同步问题
采集过程中遇到过一个很隐蔽的问题:mmWaveStudio的帧率并不严格均匀。官方宣称25fps,实际每帧之间的间隔有微小抖动,长时间运行后某些帧会出现重复或丢失,导致标签的帧索引和实际帧内容对不上。这个问题在数据量大时会被放大,甚至会造成训练时模型看到一个不连续的跳跃动作。
解决方法是在导出数据时对每帧打时间戳,并计算实际帧间隔。mmWaveStudio可以通过CCI接口获取帧计数,我用这个计数在后期做重采样对齐。每个样本保存时记录起始和结束的系统时间戳,标签时间码和帧索引同时存。
如果发现帧间隔异常大(超过60ms),我通常直接把这一段数据作废重采。因为雷达数据不是视频,丢了帧不能靠插值填充,插值会产生原本不存在的虚假多普勒特征。
6.4 距离-角度分布偏差对模型的影响
模型训练完成后,在测试集上表现正常,但部署到新房间后准确率大幅下降——这是雷达感知项目最经典的泛化问题。原因在于训练数据的距离-角度分布太集中:所有样本都在1-3m的正前方采集,真实部署时人员可能在侧面、在4-5m处,动作的RD谱形态变化很大。
缓解办法是在数据集中显式加入位置多样性。每个动作类别都至少包含三个距离段(1m、2m、3m)和两个角度(正对雷达、45°斜视),虽然采集工作量翻倍,但模型部署后的鲁棒性提升是质变级别的。
另外一个容易忽略的点是雷达高度。我在后续的实验中尝试把雷达从1.2m移到2m(模拟天花板安装),同一批动作的RD谱差异非常大。如果你想做落地产品,建议一开始就明确安装高度然后在不同高度各采一部分数据,不要等到产品化阶段再补数据。
6.5 常见问题排查速查表
| 问题现象 | 可能原因 | 排查与解决 |
|---|---|---|
| RD谱上在很近距离有强干扰线 | 天线耦合或近距离障碍物 | 去掉前若干距离门,检查雷达前方是否有遮挡 |
| 目标距离与实际不符 | 参数文件与实际配置不一致 | 核对mmWaveStudio配置,做标定测试 |
| 速度分辨率太粗,动作特征模糊 | 帧周期太长或chirp数太少 | 减小帧周期,增加每帧chirp数 |
| RD谱上有人体信号但被背景覆盖 | 静态杂波过大 | 启用MTI两脉冲对消 |
| 采集过程中数据文件出现中断 | 千兆以太网丢包 | 关闭PC的电源管理,用网卡直连禁用节能模式 |
| 同一动作的能量差异极大 | 志愿者动作幅度不一致 | 制定动作规范文字稿,统一动作幅度和速度 |
| 测试集准确率明显低于验证集 | 测试集志愿者个体差异大 | 检查数据划分,确认是否有身份重叠 |
7. 数据集的后续扩展与模型评估参考
数据集建好后,我用一个轻量级CNN(3层卷积 + 2层全连接)做了初步分类实验,输入是8帧级联的RD灰度图,尺寸128×128。训练40个epoch后,测试集准确率约86%,其中walk和fall的识别率最高(超过93%),drink最低(约76%)。这个结果是合理分布——喝水动作的雷达特征最微弱,对距离、角度、志愿者的个体差异最敏感。
如果用ResNet18这类更强的模型,测试准确率可以提升到91%左右,但参数量大得多。实际工程中我更推荐用轻量模型加数据增强的组合,在边缘设备上的部署成本低很多。
关于模型结构的选择有一个建议:不要一开始就上时序模型(LSTM、Transformer等),先用单帧CNN建立基线。基线可以达到80%以上的准确率后,再考虑引入时间上下文。直接从时序模型开始,排查问题的难度会成倍增加。
数据集的用处不局限于这6类动作的分类。基于同样的RD谱数据,还能做跌倒检测的时序预警(在动作尚未完全发生前输出异常概率)、连续动作的分割、多人场景下的目标分离等任务。做数据集本来就是一次投入、多次复用的事,前期多花时间把数据采干净、标规范,后面每一轮模型迭代都能受益。
地址、目录结构、脚本的版本管理也要纳入项目流程。雷达数据集动辄几十GB甚至上百GB,文件命名混乱会直接让项目失控。我建议每个样本的命名包含人员编号、动作类别、采集批次、序号和时间戳,并且采集脚本自动写入一份manifest清单,记录每个文件的md5校验值。这样即使某个文件损坏,也能通过校验快速定位,不用重新翻遍整个磁盘。