Skip to content

jys62544-bot/motion_estimate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 

Repository files navigation

RadarPoseNet — 基于毫米波雷达点云的人体姿态估计

基于稀疏毫米波雷达点云,使用空间-时间双阶段 Transformer 预测人体 17 关节三维骨架坐标。

输入:雷达点云序列,每帧 (x, y, z, v) 四维特征 输出:17 关节骨架坐标序列,单位为米

为什么用雷达

摄像头 毫米波雷达
隐私 采集图像,隐私敏感 只有点云,无法识别身份
光照 暗光/强光下失效 全天候工作
穿透 墙壁遮挡即失效 可穿透薄墙/衣物
数据量 每帧百万像素 每帧几十~几百个 3D 点

核心挑战:雷达点云极其稀疏且噪声大。

模型架构

输入 (B, T, N, 4)
    ↓ Input Embedding: Linear(4→256) + LayerNorm + GELU
    ↓ Spatial Encoder: 点云内 Self-Attention + 空间位置编码 (MLP 3→256)
    ↓ Learnable Query Pooling: (B*T, N, 256) → (B*T, 256)
    ↓ Temporal Encoder: 帧间 Self-Attention + RoPE 位置编码
    ↓ Head: Linear → (B, T, 17, 3)
输出:预测骨架坐标

损失函数(4 项加权 L1):

  • L_pos:关节绝对位置(四肢权重 ×2)
  • L_root_vel:根节点(Pelvis)帧间位移
  • L_local_vel:以 Pelvis 为中心的局部姿态变化
  • L_bone:骨段长度一致性约束

快速开始

环境依赖

pip install torch>=2.0 numpy scipy tqdm tensorboard pandas matplotlib pillow

需要 CUDA 11.8+(BF16 支持)、PyTorch 2.0+(torch.compile 与 Flash Attention)

1. 数据预处理

将原始 JSON 序列切分为固定长度的训练窗口(.npz 格式):

python data_split.py --root ../datapreprocess/ --outdir dataset_split/ \
    --window 75 --trim 15 --step 5 --fix-flip
参数 说明 默认
--window 窗口帧数 75
--trim 剔除首尾不稳定帧数 15
--step 滑窗步长 5
--split train/val/test 比例 0.8 0.1 0.1
--fix-flip 启用骨架翻转修复
--seed 随机种子 42

归一化变体

  • data_split.py:以最后一帧有效点云质心为原点(主版本)
  • data_split_firstpoint.py:以第一帧为原点
  • data_split_lastframe.py:以最后一帧 Pelvis 骨架坐标为原点

2. 冒烟测试

用随机数据验证模型能否正常运行(不需要真实数据):

python smoke_test.py

3. 训练

# v1:RAM Cache 模式,预加载全部数据到内存,训练速度更快
python train_zd_v1.py

# v2:Lazy Loading 模式,内存占用低,支持 Flash Attention
python train_zd_v2.py

训练产物:

  • best_model.pth:验证 MPJPE 最优的模型权重
  • runs/run_YYYYMMDD_HHMMSS/:TensorBoard 日志
  • logs/run_YYYYMMDD_HHMMSS_joints.csv:各关节逐 Epoch MPJPE

4. 监控与分析

# TensorBoard(实时监控损失、MPJPE、3D 可视化)
tensorboard --logdir runs/

# 分析 CSV 结果(修改文件内路径后运行)
python res_show.py

数据格式

原始数据../datapreprocess/):按子文件夹组织的 JSON 序列文件。

{
  "pointcloud_data": {
    "points": [{"x": 1.23, "y": 0.45, "z": 0.78, "v": -0.5}, ...]
  },
  "skeleton_data": {
    "joints": {
      "HEAD": {"x": ..., "y": ..., "z": ...},
      "NECK": {"x": ..., "y": ..., "z": ...},
      "...共17个关节..."
    }
  }
}

处理后数据dataset_split/train|val|test/*.npz):

  • pointcloud:object array,shape (T,) → 每帧 (N, 4),N 可变
  • skeleton:float32,shape (T, 17, 3),以参考帧点云质心归一化

17 关节定义(索引 0-16):

              [0] Head
                │
              [1] Neck
             ╱  │  ╲
 [5]L_Sho  [2]Chest  [8]R_Sho
     │         │         │
 [6]L_Elb  [3]Navel  [9]R_Elb
     │         │         │
 [7]L_Wri  [4]Pelvis [10]R_Wri  ← 根节点
           ╱       ╲
     [11]L_Hip   [14]R_Hip
          │            │
     [12]L_Kne   [15]R_Kne
          │            │
     [13]L_Ank   [16]R_Ank

v1 vs v2 选择指南

v1 v2
数据加载 RAM Cache(全量预加载) Lazy Loading(按需读取)
内存占用
训练速度 更快(无 I/O 开销) 受磁盘 I/O 限制
Spatial Attention nn.MultiheadAttention F.scaled_dot_product_attention(Flash Attention)
空间编码器层数 1 层 2 层
每帧点数 150 120
适用场景 内存 ≥ 32GB,追求速度 内存受限或数据集很大

关键配置

参数 v1 v2 说明
points_per_frame 150 120 每帧采样/补零到固定点数
dim_model 256 256 Transformer 隐层维度
num_spatial_layers 1 2 空间编码器层数
num_temporal_layers 5 5 时序编码器层数
batch_size 128 124
lr 5e-4 8e-4 AdamW 学习率
epochs 300 300 EarlyStopping patience=20

调度器:CosineAnnealingWarmRestarts(T_0=10, T_mult=2) 精度:bfloat16

评估指标

MPJPE(Mean Per Joint Position Error):各关节预测与真实坐标的平均欧氏距离,单位毫米(mm),数值越小越好。

代码同时记录全部 17 个关节的独立 MPJPE,可用于分析各部位的预测难度。

文件结构

motion_estimate/
├── data_split.py              # 数据预处理(主版本)
├── data_split_firstpoint.py   # 预处理变体(第一帧归一化)
├── data_split_lastframe.py    # 预处理变体(骨架归一化)
├── train_zd_v1.py             # 训练脚本(RAM Cache)
├── train_zd_v2.py             # 训练脚本(Lazy + Flash Attn)
├── smoke_test.py              # 冒烟测试
├── res_show.py                # 结果分析可视化
└── docs/
    └── project_technical_guide.md  # 详细技术文档

详细文档

完整的架构原理、代码对应关系和参数调优建议,请参考 docs/project_technical_guide.md

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages