Skip to content

AngelSky123/PerceptAlign

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 

Repository files navigation

PerceptAlign × MMFi: Cross-Environment WiFi CSI 3D Pose Estimation

基于 PerceptAlign 框架,适配 MMFi 数据集,实现跨环境(跨域)WiFi CSI 3D 人体姿态估计。


目录


研究背景

WiFi CSI 3D 人体姿态估计的核心挑战在于跨环境泛化:不同房间的多径环境导致 CSI 分布差异巨大,在源域(如 E01-E03)训练的模型直接迁移到新环境(E04)时性能会大幅下降。

PerceptAlign 是一个基于 Geometry-Conditioned Transformer 的 WiFi 姿态估计框架,原始设计针对自采数据集(5 个场景,含几何标定信息)。本项目将其适配到 MMFi 公开数据集,用于系统研究跨环境域自适应问题。

任务定义:

  • 输入:WiFi CSI 信号(3 接收天线 × 114 子载波 × 10 packets/帧)
  • 输出:17 个人体关节的 3D 坐标(H36M 骨架)
  • 源域:E01、E02、E03(有 CSI + 姿态标注)
  • 目标域:E04(用于测试泛化能力)

方法概述

PerceptAlign 模型架构

WiFi CSI (per frame, per receiver)
    │
    ▼
┌───────────────────────────────────┐
│  CSI → 3-Channel Image (224×224)  │   Phase / Amplitude / Doppler
│  × 3 receivers × T frames        │
└───────────────────────────────────┘
    │
    ▼
┌───────────────────────────────────┐
│  ResNet-34 CNN Backbone           │   每帧每天线提取 256-d 特征
│  (GroupNorm, no BatchNorm)        │
└───────────────────────────────────┘
    │
    ▼
┌───────────────────────────────────┐
│  Token Construction (Eq. 24)      │   u_{n,t} = LN(W_f·f + W_e·e + r_t + s_n)
│  ├── f: CNN 特征                  │
│  ├── e: 空间嵌入 (NeRF PE)       │
│  ├── r_t: 时间嵌入               │
│  └── s_n: 天线偏置               │
└───────────────────────────────────┘
    │  T×Nr = 29×3 = 87 tokens
    ▼
┌───────────────────────────────────┐
│  Transformer Encoder (4 layers)   │   联合时空注意力
│  d_model=512, 8 heads             │
└───────────────────────────────────┘
    │
    ▼
┌───────────────────────────────────┐
│  Keypoint Decoder (MLP)           │   每帧输出 17×3 坐标
│  Nr×512 → 1024 → 512 → 51        │
└───────────────────────────────────┘

CSI 图像化处理

MMFi 的每帧 .mat 文件(3 天线 × 114 子载波 × 10 packets)通过以下方式转换为 PerceptAlign 需要的 3 通道图像:

通道 内容 物理意义
Channel 0 归一化振幅 信号强度,反映人体遮挡和多径衰落
Channel 1 Unwrap 相位 携带距离和运动信息
Channel 2 子载波相位差 Doppler 频移近似,对运动敏感

seg_len=10 帧合并后,CSI 的时频矩阵 (114, 100) 通过双线性插值 resize 到 (224, 224) 以适配 ResNet-34 输入。


项目结构

PerceptAlign/
├── perceptalign/                    # PerceptAlign 源码(不修改)
│   ├── models/
│   │   └── perceptalign.py          # posenet 模型定义
│   ├── data/
│   │   └── actions.py               # 数据加载器
│   └── config.py                    # 默认配置
│
├── tools/
│   ├── train.py                     # 训练脚本(原始)
│   ├── eval.py                      # 评估脚本(原始)
│   ├── preprocess.py                # 原始数据预处理
│   ├── preprocess_mmfi.py           # ✨ MMFi 数据预处理
│   └── verify_mmfi_pt.py            # ✨ 预处理结果验证
│
├── configs/
│   ├── cross_env_mmfi_E04.yaml      # ✨ 跨环境: E01+E02+E03 → E04
│   ├── cross_env_mmfi_E01.yaml      # ✨ 跨环境: E02+E03+E04 → E01
│   ├── within_env_E04.yaml          # ✨ 域内基线 (上界)
│   └── cross_layout_scene3_*.yaml   # 原始配置
│
├── data/
│   └── preprocessed_actions/        # 预处理输出目录
│       ├── MMFi/pt/*.pt             # 转换后的 .pt 文件
│       ├── manifest.json            # 数据清单
│       └── manifest.jsonl           # JSONL 版本
│
├── weights/                         # 模型权重保存目录
├── MMFi/                            # MMFi 原始数据(需自行放置)
│   ├── E01/S01/A01/wifi-csi/...
│   ├── E02/...
│   ├── E03/...
│   └── E04/...
│
└── README.md                        # 本文件

标注 ✨ 的文件为 MMFi 适配新增,其余为 PerceptAlign 原始代码。


环境配置

依赖

  • Python 3.7+
  • PyTorch >= 1.12(已测试 PyTorch 1.13 + CUDA 11.7)
  • torchvision(与 PyTorch 版本匹配)
  • scipy, h5py, numpy, tqdm, pyyaml, matplotlib

安装

# 创建虚拟环境(可选,已有环境可跳过)
conda create -n perceptalign python=3.7
conda activate perceptalign

# 安装 PyTorch(根据 CUDA 版本选择)
pip install torch==1.13.0+cu117 torchvision==0.14.0+cu117 \
    --extra-index-url https://download.pytorch.org/whl/cu117

# 安装其他依赖
pip install scipy h5py tqdm pyyaml matplotlib

验证安装

python -c "import torch; print(torch.__version__, torch.cuda.is_available())"
python -c "import scipy; import h5py; import yaml; print('OK')"

数据集准备

MMFi 数据集

MMFi 数据集需要自行下载,放置在项目目录或任意位置,目录结构如下:

MMFi/
├── E01/                          # 环境 1
│   ├── S01/                      # 被试 1
│   │   ├── A01/                  # 动作 1
│   │   │   ├── wifi-csi/         # CSI 数据
│   │   │   │   ├── frame_000001.mat
│   │   │   │   ├── frame_000002.mat
│   │   │   │   └── ...           # ~297 帧
│   │   │   └── ground_truth.npy  # 姿态标注 (F, 17, 3)
│   │   ├── A02/
│   │   └── ...                   # A01-A27,共 27 种动作
│   ├── S02/
│   └── ...                       # S01-S10
├── E02/                          # S11-S20
├── E03/                          # S21-S30
└── E04/                          # S31-S40

数据规模:

环境 被试 动作 帧数/动作 总样本数
E01 S01-S10 A01-A27 ~297 270 sequences
E02 S11-S20 A01-A27 ~297 270 sequences
E03 S21-S30 A01-A27 ~297 270 sequences
E04 S31-S40 A01-A27 ~297 270 sequences
合计 40 人 27 种 1080 sequences

CSI 数据格式

每个 .mat 文件包含:

  • CSIamp: float32 (3, 114, 10) — 振幅(3 接收天线 × 114 子载波 × 10 packets)
  • CSIphase: float32 (3, 114, 10) — 相位

姿态标注格式

ground_truth.npy: float32 (F, 17, 3) — F 帧的 17 关节 3D 坐标(米),遵循 H36M 骨架定义。


数据预处理

将 MMFi 原始数据转换为 PerceptAlign 的 .pt 格式。

运行预处理

cd ~/PerceptAlign

python tools/preprocess_mmfi.py \
    --mmfi_root /path/to/MMFi \
    --out_root data/preprocessed_actions \
    --envs E01 E02 E03 E04 \
    --seg_len 10

参数说明:

参数 默认值 说明
--mmfi_root (必填) MMFi 数据集根目录
--out_root (必填) 预处理输出目录
--envs E01 E02 E03 E04 要处理的环境列表
--seg_len 10 每输出帧聚合的原始帧数
--image_size 224 输出图像分辨率
--overwrite False 是否覆盖已有 .pt 文件

预期输出:

[progress] saved=270 skipped=0 current=E01/S10/A27 T_out=29
[progress] saved=540 skipped=0 current=E02/S20/A27 T_out=29
[progress] saved=810 skipped=0 current=E03/S30/A27 T_out=29
[progress] saved=1080 skipped=0 current=E04/S40/A27 T_out=29
[done] saved=1080 skipped=0
[stats] per-environment: {'E01': 270, 'E02': 270, 'E03': 270, 'E04': 270}

每个 .pt 文件约 30-50MB,总计约 30-50GB 磁盘空间。

验证预处理结果

python tools/verify_mmfi_pt.py \
    --pt_dir data/preprocessed_actions/MMFi/pt \
    --max_files 5

预期输出:

[OK] E01_S01_A01.pt
  csi_data:  (29, 3, 3, 224, 224)  dtype=torch.float32  range=[0.000, 1.000]
  keypoints: (29, 17, 3)           dtype=torch.float32  range=[-0.xxx, 0.xxx]
  scene=MMFi  user=S01  action=A01  layout=E01

[ALL OK] 所有文件格式正确, 可以开始训练。

训练

跨环境训练(主实验)

cd ~/PerceptAlign

# E01 + E02 + E03 → E04
PYTHONPATH=. python tools/train.py --config configs/cross_env_mmfi_E04.yaml

如果配置中使用相对路径报错,请修改为绝对路径:

# 自动修改配置为绝对路径
sed -i "s|preprocessed_root: data/|preprocessed_root: $(pwd)/data/|" configs/cross_env_mmfi_E04.yaml
sed -i "s|manifest: data/|manifest: $(pwd)/data/|" configs/cross_env_mmfi_E04.yaml
sed -i "s|weights_dir: weights|weights_dir: $(pwd)/weights|" configs/cross_env_mmfi_E04.yaml
sed -i "s|outputs_dir: outputs|outputs_dir: $(pwd)/outputs|" configs/cross_env_mmfi_E04.yaml

多卡训练(DDP)

PYTHONPATH=. torchrun --nproc_per_node=2 tools/train.py \
    --config configs/cross_env_mmfi_E04.yaml

显存不足时调整

编辑 configs/cross_env_mmfi_E04.yaml

data:
  batch_size: 1          # 从 2 降到 1
train:
  grad_accum: 16         # 从 8 增到 16,保持等效 batch size

训练日志

[epoch 1/200] val: MPJPE=xxx.xxmm PCK@20=xx.xx% PCK@50=xx.xx% lr=1.000e-04
[epoch 2/200] val: MPJPE=xxx.xxmm PCK@20=xx.xx% PCK@50=xx.xx% lr=1.000e-04
[save] best -> weights/cross_env_mmfi_E04_best.pth
...

模型权重自动保存在 weights/ 目录,文件名为 {experiment_name}_best.pth


测试与评估

PYTHONPATH=. python tools/eval.py \
    --config configs/cross_env_mmfi_E04.yaml \
    --checkpoint weights/cross_env_mmfi_E04_best.pth \
    --split test \
    --amp

输出格式:

[test] MPJPE=xxx.xx mm | PCK@20=xx.xx% | PCK@50=xx.xx%

评估不同 split

# 测试集 (目标域 E04)
PYTHONPATH=. python tools/eval.py --config ... --split test

# 验证集 (源域的 10% 留出)
PYTHONPATH=. python tools/eval.py --config ... --split val

# 训练集 (检查过拟合)
PYTHONPATH=. python tools/eval.py --config ... --split train

实验配置说明

已提供的配置

配置文件 训练域 测试域 用途
cross_env_mmfi_E04.yaml E01, E02, E03 E04 主实验:跨环境泛化
cross_env_mmfi_E01.yaml E02, E03, E04 E01 消融实验
within_env_E04.yaml E04 E04 域内基线(性能上界)

自定义新实验

以 "E02+E04 训练 → E03 测试" 为例:

# configs/cross_env_mmfi_E03.yaml
experiment:
  name: cross_env_mmfi_E03

protocol:
  type: cross_layout
  scene: MMFi
  train_layouts: [E02, E04]
  test_layouts: [E03]

# 其余配置与 cross_env_mmfi_E04.yaml 相同

关键超参数

参数 默认值 说明
model.num_keypoints 17 H36M 关节数(不要改)
model.num_layers 4 Transformer 层数
model.num_heads 8 注意力头数
model.max_seq_len 60 最大序列长度(>29 帧即可)
train.lr 1e-4 初始学习率
train.epochs 200 训练轮数
train.grad_accum 8 梯度累积步数
data.batch_size 2 批大小(受显存限制)

评估指标

指标 说明 方向
MPJPE 平均关节位置误差(mm),预测与 GT 的欧氏距离均值 越小越好
PCK@20mm 关节误差 < 20mm 的比例 越大越好
PCK@50mm 关节误差 < 50mm 的比例 越大越好

注:PerceptAlign 的 MPJPE 在根节点中心化的坐标系中计算,已消除全局位置偏移。


关键设计说明

MMFi ↔ PerceptAlign 概念映射

MMFi 概念 PerceptAlign 对应 适配方式
环境 (E01-E04) Layout (A/B/C) layout 字段映射环境编号
被试 (S01-S40) User user 字段直接对应
动作 (A01-A27) Action action 字段直接对应
3 接收天线 3 Receivers 天线 = 接收器,物理对应
114 子载波 57 subcarriers MMFi 频率分辨率更高
17 关节 (H36M) 25 关节 (SMPLX) config 中设置 num_keypoints: 17
无几何标定 tx/rx 坐标 不使用几何条件化,receiver_bias 自动学习

为什么不需要修改 PerceptAlign 源码

  1. 几何条件化是可选的:当 .pt 中没有 tx_coords/rx_coords 时,train.py 自动跳过几何计算,receiver_bias 参数学习天线间差异。

  2. 关节数通过 config 控制num_keypoints: 17 传入 posenet 构造函数,自动调整 decoder 输出维度。

  3. 数据格式完全兼容:预处理脚本生成的 .pt 与 PerceptAlign 的 ManifestPTDataset 完全兼容。

  4. 协议框架复用:MMFi 的跨环境设定映射为 cross_layout 协议,环境编号作为 layout 标签。

预处理细节

CSI 帧聚合:每 seg_len=10 帧合并为 1 个输出帧。297 原始帧 → 29 输出帧,每帧的 CSI 包含 100 个 packets 的信息(10 帧 × 10 packets)。

根节点中心化:预处理时对 keypoints 做根节点中心化(第一帧 Hip 关节 = 原点),与 PerceptAlign 原始流程一致。

存储开销:每个 .pt 约 30-50MB(主要是 224×224 图像),1080 个文件共约 30-50GB。


常见问题

Q: ModuleNotFoundError: No module named 'perceptalign'

项目未安装到 Python 路径。使用 PYTHONPATH 运行:

PYTHONPATH=. python tools/train.py --config ...

或安装为可编辑包(如果项目有 setup.py):

pip install -e .

Q: FileNotFoundError: ... manifest.json

配置中的路径是相对于 config 文件所在目录解析的。改为绝对路径:

# 自动修改
sed -i "s|preprocessed_root: data/|preprocessed_root: $(pwd)/data/|" configs/cross_env_mmfi_E04.yaml
sed -i "s|manifest: data/|manifest: $(pwd)/data/|" configs/cross_env_mmfi_E04.yaml
sed -i "s|weights_dir: weights|weights_dir: $(pwd)/weights|" configs/cross_env_mmfi_E04.yaml

Q: 预处理时所有样本都 skip(saved=0 skipped=1080

检查报错信息。如果是 _stack_dispatcher() got an unexpected keyword argument 'dim',需要修正 numpy 调用:

sed -i 's/np.stack(keypoints, dim=0)/np.stack(keypoints, axis=0)/g' tools/preprocess_mmfi.py

Q: 训练时 GPU 显存不足(OOM)

调小 batch_size 并增大 grad_accum 以保持等效 batch size:

data:
  batch_size: 1
train:
  grad_accum: 16

Q: 训练速度很慢

  • 开启 AMP 混合精度:确保配置中 data.amp: true
  • 减少 num_workers 如果 CPU 是瓶颈
  • 降低图像分辨率(需重新预处理):--image_size 112

Q: 如何添加新的跨环境实验?

复制 cross_env_mmfi_E04.yaml,修改 train_layoutstest_layouts

protocol:
  train_layouts: [E01, E03]
  test_layouts: [E02]

Q: 预处理后磁盘空间不够

可以减小图像尺寸和增大帧聚合数:

python tools/preprocess_mmfi.py \
    --mmfi_root /path/to/MMFi \
    --out_root data/preprocessed_actions \
    --seg_len 15 --image_size 112 --overwrite

这会将存储从 ~40GB 降至 ~5GB,但可能影响精度。


致谢

  • PerceptAlign — Geometry-Aware WiFi Sensing 框架
  • MMFi — 多模态 WiFi 感知数据集

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages