第一次在实验室里拿到 WiFi CSI 数据的时候,屏幕上跳动的波形密密麻麻,看起来像一堆没有规律的心电图。我当时盯着那几条曲线看了很久,脑子里只有一个问题:这玩意儿真的能“感知”出房间里的人在走路、呼吸甚至摔倒吗?后来把整套链路跑通,从数据采集、信号处理一路推到产品原型,我才真正意识到,WiFi CSI 感知技术并不是实验室里自嗨的玩具,它是一条非常值得梳理的、从学术研究走向行业落地的完整技术路径。
这篇文章想做的,就是把这条路径完整铺开给你看。不管你是刚接触 CSI 的研究生,还是正在评估智能家居、养老监护、车载感知方案的工程师,又或者是想给自己的物联网产品增加“无感感知”能力的产品经理,下面这些内容应该都能帮你节省大量的踩坑时间。我会从 CSI 的物理意义讲起,讲清楚采集端怎么选,预处理怎么做,识别模型怎么落地,最后再聊聊那些从学术 demo 走向产品时最容易翻车的工程问题。
1. 为什么无线感知非要选 CSI 而不是 RSSI
1.1 RSSI 的局限:一锅端的总能量
很多人第一次接触无线感知时,第一反应是把目光投向 RSSI,也就是 WiFi 信号强度指示。原因是它的获取成本最低,几乎任何一台 WiFi 设备都能直接读出当前接收信号的强度值。但问题也恰恰出在“强度值”这三个字上:RSSI 是接收端对整个信道、所有多径分量叠加之后的综合能量打的一个分,它只是一个标量,没有任何频率维度上的细节。
打个比方,RSSI 就像你站在一间音乐厅门口,只能听到整场演出混在一起的响度有多大。你永远分不清是哪把小提琴在哪个位置拉出了哪几个音符。WiFi 信号在室内传播时会经过墙面的反射、人体散射、家具的边缘衍射,这些路径叠加在一起,最终在接收天线那里形成一张非常复杂的多径干扰图。RSSI 把这张图折叠成了一个数,大量关于环境细节的信息在这个过程中被丢掉了。
1.2 CSI 拿到了“分频段的体检报告”
CSI 全称 Channel State Information,直译是信道状态信息。它描述了无线信号从发送端到接收端的过程中,信道在每个子载波上对信号造成的幅度衰减和相位偏移。换句话讲,CSI 不是一个总强度,而是一组数据:每一个子载波都有自己的幅度和相位。在一个 20 MHz 带宽的 802.11n 信号里,接收端可以提取出 30 个左右有效子载波的 CSI,每个子载波对应一个窄带频率,相当于把整段频带切开来看。
这就像是同样听音乐厅的演出,RSSI 只给你一个总音量,而 CSI 给了你一张光谱图,哪个频率分量强、哪个频率分量弱、相位发生了什么变化,全都清清楚楚。正因为有了频率维度的分辨能力,CSI 才能捕捉到呼吸引起的胸腔微小起伏、手臂摆动带来的散射路径变化、甚至一个人从站立到跌倒的剧烈多径变化。这些都是 RSSI 做不到的。
从学术研究的角度看,2011 年华盛顿大学团队的“WiSee”和后来的一系列 CSI 工作,把无线感知的准确率从 RSSI 时代的边缘水平拉到了可接受区间。到今天我接触过的跌倒检测项目里,基于 CSI 的方案在单房间、单设备部署下已经把误报率压到了接近商用雷达的水平,而成本却低得多。
1.3 采集链路里藏着哪些信息
要理解 CSI 为什么能感知人体活动,得先明白 WiFi 信号在室内是怎么走的。发射端发出一个 OFDM 符号后,这个符号会沿着多条路径到达接收端:直达路径、墙面反射路径、地面反射路径、人体反射路径。接收端得到的信号是这些路径的矢量和。当人体移动时,人体反射路径的长度和方向在变,叠加后的矢量自然也就在变,最终表现为每个子载波上 CSI 幅度和相位的波动。
所以 CSI 感知的本质,是拿无线信道当传感器,把环境中“物体运动”这个物理变化映射成“信道响应变化”这个可测量量。你不需要戴任何终端设备,不需要摄像头,不需要红外传感,只要房间里有 WiFi 信号覆盖,感知能力顺手就来了。这也是它在隐私敏感场景里特别受欢迎的原因——它看不见图像,听不见声音,却知道房间里在发生什么。
2. 数据采集与硬件选型:别在第一步就走弯路
2.1 四种主流 CSI 采集方案
在实验室里体验过和真正动手搭采集系统之间,隔着一道硬件选型的坎。我记得自己最早的项目用的是 Intel 5300 网卡,这套方案在学术界已经被用了十几年,配套的 CSI Tool 可以把 30 个 子载波的 CSI 数据从网卡驱动里捞出来,再转成 MATLAB 能分析的格式。优点是资料多、网上踩坑记录齐全,缺点是硬件只有 2.4 GHz 频段、802.11n 协议,放到现在的 WiFi 6 环境里已经有点跟不上场景了。
Atheros 方案是另一支学术主流,ATH9K 芯片的开放驱动配合 CSI Tool,可以拿到更细粒度的信道数据。它的灵活性比 Intel 5300 好不少,但配置过程对新手不太友好,需要刷特殊内核模块,我在第一次编译驱动时遇到过内核版本不匹配的问题,折腾了大半个周末才跑通。如果你不是软件底层老手,这条路建议放在第二步再尝试。
Nexmon 方案是后来发展起来的固件级采集方案,基于博通芯片做 CSI 提取,在树莓派等平台上很流行。它的优势是配合 Raspberry Pi 和 Nexmon CSI Tool,你可以在不侵入系统内核的情况下拿到 CSI 数据,而且支持 5 GHz 频段,数据质量更高。很多新的学术工作都在往这个方向迁移。
最后是 ESP32 方案。这块芯片可能是物联网圈最熟悉的面孔,价格便宜到可以当成耗材来用。随着 ESP32 CSI Toolkit 的成熟,它也就能通过开启 promiscuous 模式获取附近接入点的 CSI 数据了。它的优点非常明显:成本低、部署灵活、有完善的 SDK 文档,产品原型可以直接往这个方向集成。缺点是 CSI 数据的子载波数量、帧同步质量不如前面几个专用方案,需要后期处理下功夫。
2.2 不同方向的选型建议
| 采集方案 | 频段支持 | 获取难度 | 成本 | 数据处理量 | 适合场景 |
|---|---|---|---|---|---|
| Intel 5300 | 2.4 GHz | 低 | 中 | 中 | 学术复现、算法验证 |
| Atheros ATH9K | 2.4/5 GHz | 高 | 中 | 中 | 细粒度信道研究 |
| Nexmon + 树莓派 | 2.4/5 GHz | 中 | 中 | 中 | 新方案验证、数据集构建 |
| ESP32 系列 | 2.4 GHz | 低 | 极低 | 偏低 | 快速原型、产品探索 |
如果你是在做产品化验证,我的建议是优先考虑 ESP32。不是为了技术情怀,而是因为它更容易落地到真实的商业逻辑里。一套 ESP32 模组的物料成本可能只有十几块钱人民币,就算你需要在家里部署十几个感知节点,成本压力也远远小于用专用网卡。最重要的是,ESP32 的 CSI 功能并不需要改基础设施,它只是监听空间里已有的 WiFi 信号,产品形态可以做到极其轻薄。
2.3 我踩过的数据一致性坑
这里要特别提醒一句:无论你选哪个方案,采集阶段一定要把发送端和接收端的相对位置固定下来,尤其是天线朝向。CSI 数据对天线摆放非常敏感,天线方向差个 10 厘米或者旋转 30 度,特征分布就会明显偏移。我在一次呼吸监测实验里,把接收设备从桌面挪到了窗台上,前后只移动了半米,模型的误差率直接翻了一倍。
另外一个很容易忽略的问题是发包速率和功率。如果你用 ESP32 做接收,建议设置一个固定的发包间隔,比如每秒 100 个包,并保持发射功率恒定。功率一旦波动,CSI 幅度会受自动增益控制的影响出现跳变,这种跳变跟人体活动混在一起后非常难分离,会严重污染后续的特征提取。
3. 信号处理链路:拿到 CSI 之后的九道工序
3.1 原始数据里的脏东西
很多初学者拿到 CSI 数据后,第一反应是直接画幅度曲线观察规律,然后发现曲线里全是毛刺,几乎看不出明显的周期性。这是非常正常的。原始 CSI 数据里混着载波频率偏移、采样频率偏移、包检测延迟、接收端自动增益控制变化,还有环境里微波炉、蓝牙设备的偶发干扰。这些噪声不去掉,后面的模型训练基本就是白忙活。
我自己的标准预处理流程通常分为四步。第一步是清洗,把明显异常的数据帧剔除掉,比如幅度值超出物理范围、相位跳变超过阈值的帧。第二步是幅度平滑,用滑动平均或者中值滤波把高频毛刺压下去,窗口大小一般选 5 到 20 个采样点,具体取决于你的发包率。第三步是相位校正,这个单独拎出来说。第四步是把静态分量和动态分量分离,用高通滤波器滤掉环境中固定物体的反射贡献,把人体的动态信号留下来。
3.2 相位校正到底在解决什么
CSI 的相位信息理论上是有用的,但实际拿到的相位值几乎都是“病”的。原因在于 WiFi 收发芯片的时钟并不是完全同步的,存在载波频率偏移和采样频率偏移,这会在相位的测量值上叠加一个随包变化的随机偏移。如果你不管它直接提取相位特征,看到的就是一堆不可复现的随机数。
标准做法是用线性拟合方式估计相位偏移并进行补偿。因为子载波偏移引起的相位误差与子载波索引成线性关系,你可以把所有子载波的原始相位画出来,拟合出一条直线,把这条直线的斜率和截距剥离掉,剩下的才是反映真实信道状态的相位。这一步很关键,我见过不少团队跳过相位校正,只凭幅度做模型,虽然也能出效果,但在动作幅度较细的场景里,比如呼吸监测或微手势识别,准确率的差距立刻拉开到十个点以上。
3.3 有用的特征其实没那么多
预处理干净之后,接下来要考虑的就是特征提取。很多人在这一步本能地想堆特征,把均值、方差、过零率、功率谱密度、小波系数全都塞进模型,结果训练时过拟合,测试时泛化差。我个人的原则是:先用物理常识把特征压缩到最小集合,再根据实验回放来补充。
对于人体活动识别,我最常用的特征包括每个子载波的幅度方差、相邻窗口的幅度变化率、整个频带的主频能量占比。对于呼吸监测,核心特征就是相位或幅度序列的功率谱峰值频率,因为正常呼吸的频率范围非常窄,大约在 0.2 到 0.6 Hz 之间,你只要在这个区间内找到能量最强的频率分量,再平滑一下时序,就能得到相当稳定的呼吸率。过零率在活动识别里也很有用,它反映了 CSI 波形穿越平均值的频率,静止时很低,走动时显著升高,这一单特征就能撑起一个初步的动静检测模型。
4. 感知建模:从波形差异到场景理解
4.1 三类主流感知案例的实现逻辑
CSI 感知的典型应用场景,大致可以分成三类:活动识别、生理信号监测、被动定位。活动识别的核心是:不同动作对多径信道的扰动模式不同。走路时身体大范围移动,子载波幅度会出现整体性的高频波动;坐下时上半身前倾,靠近胸口位置的天线会捕捉到一段低频、缓慢的幅度变化;摔倒时先是一个剧烈的冲击式波动,然后归于平静。利用这种时序模式,就能训练模型区分不同动作。
生理信号监测最典型的是呼吸检测。人体呼吸时胸腔起伏幅度只有几毫米到一厘米,但这足以对 WiFi 信号产生可测的相位扰动。把 CSI 的相位序列经过带通滤波后,就能看到非常规律的周期波,频率和呼吸频率高度吻合。心率检测相对难一些,因为心跳引起的体表振动更微小,需要更高精度的采集环境和更干净的信号质量。
被动定位的核心逻辑则略有不同。它是利用“人在不同位置会形成不同多径特征”这一事实,把位置匹配问题转化为信号指纹匹配问题。你需要在目标区域内部署若干参考接收点,预先采集人在每个位置时的 CSI 指纹库,在线识别时把当前 CSI 特征跟指纹库比对,输出概率最大的位置。这跟 RSSI 指纹定位的原理类似,但 CSI 指纹的维度更高、区分度更好,定位精度可以从米级提升到亚米级。
4.2 模型输入端长什么样
无论你用传统机器学习还是深度学习,模型的输入基本上是一个三维张量:天线对数 × 子载波数 × 时间窗口。比如某组实验用两个天线对、30 个子载波、5 秒窗口、每秒 100 包,那输入就是一个 2 × 30 × 500 的矩阵。很多团队直接把这个矩阵压平后喂给全连接网络,效果一般。比较有效的做法是先把它转成特征图,把子载波看作“空间维度”、时间看作“时间维度”,用 CNN 或 LSTM 处理。
我的经验是,在没有大量训练数据的前提下,先用传统方法打底更务实。把 5 秒窗口内的幅度方差、逐子载波的幅度斜率、相邻帧变化量、主频峰值、频带能量比这几个特征提出来,训练一个随机森林或 SVM,往往就已经能到 85% 到 90% 的准确率了。只有当你需要识别非常相似的动作,比如左转和右转、前倾和后仰这类细粒度分类时,深度学习才会体现出它的优势。
4.3 一个小而有效的活动识别样例
为了让整个流程更具体,我拿一个跌倒识别样例来说。采集端用 2 根天线接收 CSI,发包率 100 Hz,窗口长度 2 秒,每 0.5 秒滑动一次。预处理阶段做幅度平滑和相位校正,然后用方差特征检测波动峰值。当波动峰值的幅度超过正常活动水平的 2.5 倍,并且随后 1 秒内 CSI 能量迅速回落到接近静止水平,就判定为一次跌倒事件。
这个规则简单到可能你觉得不像“人工智能”,但在真实场景里它的可靠性很高。因为跌倒和普通活动的区别不在于复杂度,而在于时序结构:先剧烈、后静止。用一个双阈值逻辑比你堆很多模型参数要稳定得多,计算量也可以忽略不计。当然,如果你想区分“跌倒后还能爬起来”和“跌倒后长时间不动”,只要在后处理里再加一段对静止时长的判断就行。
5. 从实验室到产品的工程化拆解
5.1 跨设备和跨环境的泛化问题
实验室里训练出的模型搬到用户家里,准确率掉一半,这是 CSI 产品化最经典的翻车现场。原因在于 CSI 数据和部署环境、设备型号强相关。不同网卡的固件版本不同,自动增益控制的阈值不同,天线的极化方向不同,都会导致特征分布偏移。更别提用户家庭的户型、家具材质、路由器摆放位置了。同一个动作,在 A 实验室和 B 家庭里呈现出的 CSI 波形可能差得很远。
应对思路有三条。第一条是数据增强:在采集阶段有意变换设备位置、房间里物件的摆放、不同人数,让模型见过更多环境变体。第二条是特征规范化:把 CSI 幅度按自身均值和标准差做标准化,让模型不过度依赖绝对信号强度。第三条是迁移学习:在产品端部署一套轻量级校准流程,让用户配合做几个指定动作,用少量数据把模型微调一下。这已经是被验证过的产品化路径了。
5.2 实时性、资源消耗与边缘部署
很多人低估了 CSI 数据的实时处理开销。以 ESP32 采集方案为例,如果你用 100 包每秒的速率采集,每个包有几十个子载波的复数数据,一秒的数据量不大,但在主控端做滑动窗特征提取、谱分析、模型推理,如果代码写得粗糙,内存和 CPU 都会吃紧。
我的建议是尽量把计算前置到数据到达的早期阶段。不要在嵌入式端直接跑深度学习,而是先把原始 CSI 在采集端完成清洗、降采样、特征提取,把几十个子载波压缩成几个标量特征,再用轻量级分类器做决策。这样既能保证实时性,又能避免把原始数据回传云端带来的隐私风险。产品端集成时,特征提取要固定使用定点运算,避免不同编译器下的浮点结果不一致。
5.3 数据标注与隐私处理
有监督模型的性能天花板由标注质量决定,但 CSI 数据天然抽象,没法像图像一样直接看到内容,标注起来非常痛苦。我见过不少团队录了几百 GB 的 CSI 数据之后,发现标签对不上时间轴,只能重来。更务实的做法是在采集阶段同步录像,然后按录像的时间点自动生成标签,省去人工肉眼辨认波形再标注的痛苦。
隐私是 CSI 感知的另一大卖点。它不需要摄像头,不采集人脸,不收录音频,从原理上就避开了很多隐私红线。但要注意,CSI 原始数据如果被恶意分析,仍然能从多径信号中反推出动作类型甚至手势内容。所以在产品架构里,我建议做端侧推理,云端只接收抽象的语义结果,比如“有人跌倒”“呼吸异常”,不接收原始 CSI 数据文件。这样即便传输链路被截获,攻击者拿到的也只是不可复原的语义标签。
6. 问题排查与提高稳定性的心得
6.1 常见异常现象和定位思路
把我在实际调试中频繁遇到的问题整理成了下面这个速查表,里面的每一项我都亲手处理过至少一次。
| 异常现象 | 可能原因 | 优先排查方向 |
|---|---|---|
| 幅度曲线随机跳变 | 发射功率不稳或自动增益控制介入 | 固定发射功率档位,关闭功率自适应 |
| 相位序列看起来一片噪声 | 相位校正未做或子载波排列顺序不对 | 重新检查相位线性拟合流程 |
| 呼吸波形周期性不明显 | 采集位置离人体过远 | 增大天线增益,或缩短收发端与目标的距离 |
| 模型训练准确率高但现场准确率低 | 环境差异或设备差异导致数据分布偏移 | 做特征标准化,采集现场少量数据微调 |
| ESP32 数据流频繁中断 | 内存不足或看门狗复位 | 优化缓冲区管理,降低发包率 |
| 特定位置识别失效 | 该位置处于信号阴影区 | 调整收发天线位置,增加感知节点 |
6.2 提高稳定性的三条经验
第一,做任何感知项目之前,先用一个最简单的小实验验证采集链路是否可靠。把收发设备固定好,让一个人坐在中间静止 30 秒再走动 30 秒,观察 CSI 幅度曲线是否能明显区分的动静区间。如果这个实验都做不出清晰差异,那问题多半在采集端,而不是后续算法。
第二,处理数据时永远保留一条检查路径。我给所有项目都保留了一个可视化脚本,把预处理后的 CSI 幅度渲染成热力图。人在走动时,热力图里会出现明显的斜向条带;静止时,热力图基本平直。这种原始可视化的判断力,胜过任何复杂的检验指标。
第三,做产品时要接受“非完美感知”的定位。CSI 感知不可能跟摄像头一样明确分辨出每个人的身份和动作细节,它的价值在于无感覆盖。一个 90% 准确率的跌倒监测加上人工确认流程,远比一个 99% 准确率但只能在特定实验室环境跑通的方案有价值。
这套技术从实验室走到产品,最需要跨越的从来不是算法精度,而是对真实环境不确定性的容忍能力。如果你正打算往这个方向投入,建议先从一个最小的场景跑通全链路,比如在你的开发板上试通 ESP32 的 CSI 采集,再结合本文的预处理流程搭出一个呼吸监测 demo。真正把每一个环节的手感建立起来之后,你会发现 CSI 感知其实不是一个遥不可及的方向,它只是需要你把每一层细节都做到位而已。