Skip to content
当前页大纲

WiFi 感知人体行为监测

领域 无线感知 · IoT · 机器学习角色 主程架构 · 核心开发状态 已落地 ·【时间待补充】#WiFi CSI#信号处理#时序分类#隐私保护

不装摄像头、不戴设备——用普通 WiFi 信号「看见」人的存在与行为:存在检测、跌倒监测、行为识别。人体扰动 WiFi 多径信道,把 CSI 信号里的扰动解码成行为语义。

摄像头监控有天然的隐私阻力(卧室、卫生间、养老院老人的尊严问题),穿戴设备有「忘戴/抗拒」问题。这个项目走第三条路:利用环境中已有的 WiFi 信号做感知——人在房间里活动时,身体会反射和散射 WiFi 电磁波,改变信道的多径结构。接收端把这些变化(CSI)采集下来,用信号处理 + 机器学习解码出「有没有人、在做什么、有没有跌倒」。没有镜头、无需穿戴、全屋覆盖、成本几乎为零

一、为什么 WiFi 能感知人体

WiFi 信号从发射端到接收端不止一条路径(直射 + 墙面反射 + 家具散射 + 人体反射)。人在环境中移动时:

  • 多普勒效应:移动速度在电磁波上的投影引起载波频偏——跑步、走路、静止的频偏特征完全不同
  • 多径扰动:身体占据/腾出某条路径,接收端 CSI 幅值和相位产生对应波动
  • 呼吸微动:即使是静卧的人,胸腔起伏也会对路径长度产生毫米级调制——静息呼吸都能被捕获

信道状态信息(CSI,Channel State Information)比传统 RSSI 细粒度高两个数量级:RSSI 是整条信道的单一强度值,CSI 把 OFDM 每个子载波(常见 56/114 个)的幅相都给了出来——相当于从「一个数」变成「一张随时间变化的谱」。

二、系统架构

┌────────────────────────────────────────────────────────┐
│ 应用层   存在检测 · 跌倒报警 · 行为统计 · 呼吸监测        │
├────────────────────────────────────────────────────────┤
│ 模型层   时序分类模型(CNN+LSTM / Transformer)          │
│          跌倒检测 · 行为识别 · 多目标分离                 │
├────────────────────────────────────────────────────────┤
│ 特征层   去噪 · 子载波筛选 · 多普勒时频图 · 统计特征       │
├────────────────────────────────────────────────────────┤
│ 采集层   CSI 采集(ESP32 / 网卡 CSI Tool)· 时间同步      │
├────────────────────────────────────────────────────────┤
│ 物理层   普通 WiFi 路由器 + 接收节点(无专用传感器)        │
└────────────────────────────────────────────────────────┘

三、采集层:CSI 从哪来

方案载频CSI 质量成本适用
ESP32(本项目主力)2.4G每包一组 CSI(幅值为主)~20 元/节点大规模部署、产品化
Intel 5300 CSI Tool2.4/5G30 子载波,科研经典二手网卡算法验证
Atheros CSI Tool2.4/5G114 子载波,含相位网卡相位敏感算法

ESP32 的采集要点:

c
// ESP32 CSI 采集核心配置:只在信道空闲时拿到完整 CSI
wifi_set_csi(true);
wifi_csi_config_t cfg = {
    .lltf_en = true,           // 长训练字段——CSI 的来源
    .htlf_en = true,           // HT-LTF:802.11n 40MHz 频宽
    .dump_ack_en = false,      // 不要 ACK 包的 CSI(噪声大)
    .val_of_dcm = 1,
};
wifi_set_csi_config(&cfg);
wifi_csi_register_cb(on_csi_received);  // 每个 WiFi 包回调一次

实战坑:采样率取决于环境中的 WiFi 流量——没人传数据就没有包、就没有 CSI。解法是接收端主动发 ICMP/UDP 探测包「喂」信道,把采样率稳在 100Hz 以上(跌倒检测的最低要求:事件持续 0.5~0.8s,需要足够的时间分辨率)。

四、特征层:把信号洗干净

原始 CSI 直接喂模型效果很差,信号处理的功夫决定了上限:

1. 去噪与去趋势

python
def preprocess(csi: np.ndarray) -> np.ndarray:
    # ① 异常子载波剔除(恒为0或全满幅的坏点)
    csi = csi[:, valid_subcarriers]
    # ② Hampel 滤波去脉冲噪声(WiFi 包冲突造成的尖刺)
    csi = hampel_filter(csi, window=5, sigma=3)
    # ③ 去直流 + 归一化:消除收发链路增益差异(分环境自校准的关键)
    csi = csi - csi.mean(axis=0)
    csi = csi / (np.abs(csi).std(axis=0) + 1e-8)
    return csi

2. 子载波筛选

不是所有子载波都对人体敏感(有的子载波落在深衰落区,全程只有噪声)。用方差贡献法动态选 Top-K 灵敏子载波——顺带解决了「换环境后部分子载波失效」的域偏移问题。

3. 多普勒时频图:行为识别的核心特征

对 CSI 幅值做滑动窗口 STFT,得到的时频图里:

  • 走路:多普勒谱上规律的「手臂-腿」双频带摆动(1~3Hz 步频谐波)
  • 跌倒:短时(<0.5s)大速度冲击 → 高多普勒分量突现后迅速归零,且之后持续静止——和「快速坐下」的唯一区别就在跌倒后无恢复活动
  • 起立/坐下:中等冲击但随后有伴随小幅调整动作
频率
         ↑   跌倒特征:瞬时宽带冲击 + 后续静默
  ██████ │      ▓▓
         │     ▓▓▓▓
         │    ▓▓▓▓▓▓
         │        ▁▁▁▁▁▁▁▁▁  ← 落地后静止
         └──────────────────→ 时间
           冲击    静默

五、模型层:时序分类

任务输入模型说明
存在检测CSI 幅值序列一维 CNN + 统计特征二分类,最难的是「无人的基线漂移」抑制
跌倒检测多普勒时频图CNN(轻量)高召回优先——漏报是事故,误报只是打扰
行为识别多子载波时序CNN + LSTM / Transformer走/坐/起/卧/跌倒等多分类

两个关键工程决策:

  1. 跌倒检测用「事件级联」而不是「逐帧分类」:先能量检测找候选事件 → 分类器判型 → 落地后静默 10s 确认 → 报警。三段式把误报率压下来(宠物跳沙发、重物落地都会被「落地后有恢复活动」这一条排掉)
  2. 模型必须轻到能跑在 ESP32 或网关上:量化后的 CNN 只有几十 KB——感知数据不该上云,行为事件才上云,这也是隐私承诺的一部分

六、最难的三件事(真实痛点)

1. 环境敏感性——换房间等于换模型

家具挪动、门窗开关都会改变多径基线。缓解手段(彻底解决至今是学界难题):

  • 在线基线自适应:慢速滑动平均跟踪环境漂移(学习率 << 人体运动频率,环境变化慢、人动快,频域上分得开)
  • 多收发对冗余:两对收发链路视角不同,环境扰动很少同时废掉两条
  • 部署时的一次性「环境校准」流程(空屋采集 30s 基线)

2. 多人分离

两个人在房间里,CSI 是混叠的。工程上可用的手段:

  • 多收发对(链路 = 准「视线」约束,两人对两条链路的扰动模式不同,配合聚类可分离)
  • 行为级统计(不追求逐人识别时:占用人数估计用奇异值变化数近似)

3. 和 WiFi 业务的共存

探测包功率、频率要克制(不能为了感知把人家的网络刷出延迟);信道跳变(路由器 DFS/自动选信道)会让 CSI 流中断,接收端要监听信道事件并触发重新校准。

七、性能指标

指标数值
存在检测准确率【待补充】
跌倒检测召回/精确率【待补充】
呼吸频率估计误差【待补充】
事件报警延迟【待补充】
端侧推理耗时【待补充】

八、收获

这个项目最大的启发是换个视角看基础设施:WiFi 本来是通信管道,但它的物理层信号里藏着环境语义——「感知」不必新增传感器,解读已有信号就够了。另外对「隐私优先的设计」有了具体经验:信号不出户、模型在端侧、只上报事件语义——技术方案里每一个「多此一举」的本地化设计,在养老、医疗场景里都是产品能不能被接受的生死线。

💬 对无线感知、WiFi CSI、信号处理有想法?欢迎加我泡泡(微信)一起探讨技术与科技前沿 → 🍵 加我泡泡

MIT License.