Upload folder using huggingface_hub
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +221 -0
- .gitignore +16 -0
- LICENSE +36 -0
- README.md +75 -0
- REPROCESS_AND_TEST.md +139 -0
- ROTATION_FIX_SUMMARY.md +121 -0
- ROTATION_FIX_V2_SUMMARY.md +196 -0
- SyntheticRecorder.cs +681 -0
- TODO.md +21 -0
- _DATA/hamer_demo_data.tar.gz +3 -0
- bedlam_GT.npz +3 -0
- configs/__init__.py +30 -0
- configs/callbacks/ckpt_saver/every10000s_top100.yaml +5 -0
- configs/callbacks/lr_monitor/pl.yaml +2 -0
- configs/callbacks/metric/metric_3dpw.yaml +2 -0
- configs/callbacks/metric/metric_3dpw_occ.yaml +2 -0
- configs/callbacks/metric/metric_aistpp.yaml +2 -0
- configs/callbacks/metric/metric_emdb1.yaml +4 -0
- configs/callbacks/metric/metric_emdb2.yaml +4 -0
- configs/callbacks/metric/metric_rich.yaml +3 -0
- configs/callbacks/metric/metric_unity.yaml +4 -0
- configs/callbacks/prog_bar/prog_reporter_ed1.yaml +5 -0
- configs/callbacks/train_speed_timer/base.yaml +3 -0
- configs/callbacks/vis/vis_music.yaml +2 -0
- configs/callbacks/vis/vis_speech.yaml +2 -0
- configs/callbacks/vis/vis_text.yaml +2 -0
- configs/callbacks/vis/vis_unity_val.yaml +17 -0
- configs/data/collate_cfg/default.yaml +23 -0
- configs/data/mocap/trainX_testY.yaml +21 -0
- configs/demo.yaml +85 -0
- configs/diffusion/ddim.yaml +8 -0
- configs/endecoder/unity.yaml +2 -0
- configs/endecoder/v1_amass_local_bedlam_cam.yaml +2 -0
- configs/exp/genmo_lg.yaml +64 -0
- configs/finetune_unity.yaml +143 -0
- configs/hydra/default.yaml +19 -0
- configs/infer_video.yaml +85 -0
- configs/model/genmo.yaml +45 -0
- configs/network/diffusion.yaml +25 -0
- configs/optimizer/adamw_2e-4.yaml +2 -0
- configs/optimizer/adamw_5e-5.yaml +2 -0
- configs/pipeline/dual_mode.yaml +37 -0
- configs/scheduler/cosine_50.yaml +6 -0
- configs/scheduler/epoch_half_200_350.yaml +6 -0
- configs/test_datasets/3dpw_fliptest.yaml +3 -0
- configs/test_datasets/3dpw_occ_fliptest.yaml +3 -0
- configs/test_datasets/emdb1_fliptest.yaml +4 -0
- configs/test_datasets/emdb2_fliptest.yaml +4 -0
- configs/test_datasets/humanml3d_eval.yaml +7 -0
- configs/test_datasets/rich_test.yaml +2 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,224 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
debug_dino_init.jpg filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
third_party/GVHMR/UI/Inter_18pt-Bold.ttf filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_100.png filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_101.png filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_102.png filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_103.png filter=lfs diff=lfs merge=lfs -text
|
| 42 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_104.png filter=lfs diff=lfs merge=lfs -text
|
| 43 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_105.png filter=lfs diff=lfs merge=lfs -text
|
| 44 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_106.png filter=lfs diff=lfs merge=lfs -text
|
| 45 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_107.png filter=lfs diff=lfs merge=lfs -text
|
| 46 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_108.png filter=lfs diff=lfs merge=lfs -text
|
| 47 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_109.png filter=lfs diff=lfs merge=lfs -text
|
| 48 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_110.png filter=lfs diff=lfs merge=lfs -text
|
| 49 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_111.png filter=lfs diff=lfs merge=lfs -text
|
| 50 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_112.png filter=lfs diff=lfs merge=lfs -text
|
| 51 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_113.png filter=lfs diff=lfs merge=lfs -text
|
| 52 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_114.png filter=lfs diff=lfs merge=lfs -text
|
| 53 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_115.png filter=lfs diff=lfs merge=lfs -text
|
| 54 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_116.png filter=lfs diff=lfs merge=lfs -text
|
| 55 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_117.png filter=lfs diff=lfs merge=lfs -text
|
| 56 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_118.png filter=lfs diff=lfs merge=lfs -text
|
| 57 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_119.png filter=lfs diff=lfs merge=lfs -text
|
| 58 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_120.png filter=lfs diff=lfs merge=lfs -text
|
| 59 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_121.png filter=lfs diff=lfs merge=lfs -text
|
| 60 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_122.png filter=lfs diff=lfs merge=lfs -text
|
| 61 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_123.png filter=lfs diff=lfs merge=lfs -text
|
| 62 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_124.png filter=lfs diff=lfs merge=lfs -text
|
| 63 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_125.png filter=lfs diff=lfs merge=lfs -text
|
| 64 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_126.png filter=lfs diff=lfs merge=lfs -text
|
| 65 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_127.png filter=lfs diff=lfs merge=lfs -text
|
| 66 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_128.png filter=lfs diff=lfs merge=lfs -text
|
| 67 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_129.png filter=lfs diff=lfs merge=lfs -text
|
| 68 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_130.png filter=lfs diff=lfs merge=lfs -text
|
| 69 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_131.png filter=lfs diff=lfs merge=lfs -text
|
| 70 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_132.png filter=lfs diff=lfs merge=lfs -text
|
| 71 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_133.png filter=lfs diff=lfs merge=lfs -text
|
| 72 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_134.png filter=lfs diff=lfs merge=lfs -text
|
| 73 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_135.png filter=lfs diff=lfs merge=lfs -text
|
| 74 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_136.png filter=lfs diff=lfs merge=lfs -text
|
| 75 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_137.png filter=lfs diff=lfs merge=lfs -text
|
| 76 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_138.png filter=lfs diff=lfs merge=lfs -text
|
| 77 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_139.png filter=lfs diff=lfs merge=lfs -text
|
| 78 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_140.png filter=lfs diff=lfs merge=lfs -text
|
| 79 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_141.png filter=lfs diff=lfs merge=lfs -text
|
| 80 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_142.png filter=lfs diff=lfs merge=lfs -text
|
| 81 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_143.png filter=lfs diff=lfs merge=lfs -text
|
| 82 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_144.png filter=lfs diff=lfs merge=lfs -text
|
| 83 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_145.png filter=lfs diff=lfs merge=lfs -text
|
| 84 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_146.png filter=lfs diff=lfs merge=lfs -text
|
| 85 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_147.png filter=lfs diff=lfs merge=lfs -text
|
| 86 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_148.png filter=lfs diff=lfs merge=lfs -text
|
| 87 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_149.png filter=lfs diff=lfs merge=lfs -text
|
| 88 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_150.png filter=lfs diff=lfs merge=lfs -text
|
| 89 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_151.png filter=lfs diff=lfs merge=lfs -text
|
| 90 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_152.png filter=lfs diff=lfs merge=lfs -text
|
| 91 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_153.png filter=lfs diff=lfs merge=lfs -text
|
| 92 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_154.png filter=lfs diff=lfs merge=lfs -text
|
| 93 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_155.png filter=lfs diff=lfs merge=lfs -text
|
| 94 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_156.png filter=lfs diff=lfs merge=lfs -text
|
| 95 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_157.png filter=lfs diff=lfs merge=lfs -text
|
| 96 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_158.png filter=lfs diff=lfs merge=lfs -text
|
| 97 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_159.png filter=lfs diff=lfs merge=lfs -text
|
| 98 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_160.png filter=lfs diff=lfs merge=lfs -text
|
| 99 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_161.png filter=lfs diff=lfs merge=lfs -text
|
| 100 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_162.png filter=lfs diff=lfs merge=lfs -text
|
| 101 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_163.png filter=lfs diff=lfs merge=lfs -text
|
| 102 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_164.png filter=lfs diff=lfs merge=lfs -text
|
| 103 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_165.png filter=lfs diff=lfs merge=lfs -text
|
| 104 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_166.png filter=lfs diff=lfs merge=lfs -text
|
| 105 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_167.png filter=lfs diff=lfs merge=lfs -text
|
| 106 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_168.png filter=lfs diff=lfs merge=lfs -text
|
| 107 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_169.png filter=lfs diff=lfs merge=lfs -text
|
| 108 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_170.png filter=lfs diff=lfs merge=lfs -text
|
| 109 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_171.png filter=lfs diff=lfs merge=lfs -text
|
| 110 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_172.png filter=lfs diff=lfs merge=lfs -text
|
| 111 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_173.png filter=lfs diff=lfs merge=lfs -text
|
| 112 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_174.png filter=lfs diff=lfs merge=lfs -text
|
| 113 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_175.png filter=lfs diff=lfs merge=lfs -text
|
| 114 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_176.png filter=lfs diff=lfs merge=lfs -text
|
| 115 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_177.png filter=lfs diff=lfs merge=lfs -text
|
| 116 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_178.png filter=lfs diff=lfs merge=lfs -text
|
| 117 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_179.png filter=lfs diff=lfs merge=lfs -text
|
| 118 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_180.png filter=lfs diff=lfs merge=lfs -text
|
| 119 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_181.png filter=lfs diff=lfs merge=lfs -text
|
| 120 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_182.png filter=lfs diff=lfs merge=lfs -text
|
| 121 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_183.png filter=lfs diff=lfs merge=lfs -text
|
| 122 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_184.png filter=lfs diff=lfs merge=lfs -text
|
| 123 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_185.png filter=lfs diff=lfs merge=lfs -text
|
| 124 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_186.png filter=lfs diff=lfs merge=lfs -text
|
| 125 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_187.png filter=lfs diff=lfs merge=lfs -text
|
| 126 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_188.png filter=lfs diff=lfs merge=lfs -text
|
| 127 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_189.png filter=lfs diff=lfs merge=lfs -text
|
| 128 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_190.png filter=lfs diff=lfs merge=lfs -text
|
| 129 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_191.png filter=lfs diff=lfs merge=lfs -text
|
| 130 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_192.png filter=lfs diff=lfs merge=lfs -text
|
| 131 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_193.png filter=lfs diff=lfs merge=lfs -text
|
| 132 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_194.png filter=lfs diff=lfs merge=lfs -text
|
| 133 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_195.png filter=lfs diff=lfs merge=lfs -text
|
| 134 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_196.png filter=lfs diff=lfs merge=lfs -text
|
| 135 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_197.png filter=lfs diff=lfs merge=lfs -text
|
| 136 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_198.png filter=lfs diff=lfs merge=lfs -text
|
| 137 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_199.png filter=lfs diff=lfs merge=lfs -text
|
| 138 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_200.png filter=lfs diff=lfs merge=lfs -text
|
| 139 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_201.png filter=lfs diff=lfs merge=lfs -text
|
| 140 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_202.png filter=lfs diff=lfs merge=lfs -text
|
| 141 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_203.png filter=lfs diff=lfs merge=lfs -text
|
| 142 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_204.png filter=lfs diff=lfs merge=lfs -text
|
| 143 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_205.png filter=lfs diff=lfs merge=lfs -text
|
| 144 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_206.png filter=lfs diff=lfs merge=lfs -text
|
| 145 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_207.png filter=lfs diff=lfs merge=lfs -text
|
| 146 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_208.png filter=lfs diff=lfs merge=lfs -text
|
| 147 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_209.png filter=lfs diff=lfs merge=lfs -text
|
| 148 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_210.png filter=lfs diff=lfs merge=lfs -text
|
| 149 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_211.png filter=lfs diff=lfs merge=lfs -text
|
| 150 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_212.png filter=lfs diff=lfs merge=lfs -text
|
| 151 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_213.png filter=lfs diff=lfs merge=lfs -text
|
| 152 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_214.png filter=lfs diff=lfs merge=lfs -text
|
| 153 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_215.png filter=lfs diff=lfs merge=lfs -text
|
| 154 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_216.png filter=lfs diff=lfs merge=lfs -text
|
| 155 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_217.png filter=lfs diff=lfs merge=lfs -text
|
| 156 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_218.png filter=lfs diff=lfs merge=lfs -text
|
| 157 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_219.png filter=lfs diff=lfs merge=lfs -text
|
| 158 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_220.png filter=lfs diff=lfs merge=lfs -text
|
| 159 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_221.png filter=lfs diff=lfs merge=lfs -text
|
| 160 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_222.png filter=lfs diff=lfs merge=lfs -text
|
| 161 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_223.png filter=lfs diff=lfs merge=lfs -text
|
| 162 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_224.png filter=lfs diff=lfs merge=lfs -text
|
| 163 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_225.png filter=lfs diff=lfs merge=lfs -text
|
| 164 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_226.png filter=lfs diff=lfs merge=lfs -text
|
| 165 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_227.png filter=lfs diff=lfs merge=lfs -text
|
| 166 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_228.png filter=lfs diff=lfs merge=lfs -text
|
| 167 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_229.png filter=lfs diff=lfs merge=lfs -text
|
| 168 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_230.png filter=lfs diff=lfs merge=lfs -text
|
| 169 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_231.png filter=lfs diff=lfs merge=lfs -text
|
| 170 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_232.png filter=lfs diff=lfs merge=lfs -text
|
| 171 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_233.png filter=lfs diff=lfs merge=lfs -text
|
| 172 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_234.png filter=lfs diff=lfs merge=lfs -text
|
| 173 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_235.png filter=lfs diff=lfs merge=lfs -text
|
| 174 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_236.png filter=lfs diff=lfs merge=lfs -text
|
| 175 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_237.png filter=lfs diff=lfs merge=lfs -text
|
| 176 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_238.png filter=lfs diff=lfs merge=lfs -text
|
| 177 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_239.png filter=lfs diff=lfs merge=lfs -text
|
| 178 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_240.png filter=lfs diff=lfs merge=lfs -text
|
| 179 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_241.png filter=lfs diff=lfs merge=lfs -text
|
| 180 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_242.png filter=lfs diff=lfs merge=lfs -text
|
| 181 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_243.png filter=lfs diff=lfs merge=lfs -text
|
| 182 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_244.png filter=lfs diff=lfs merge=lfs -text
|
| 183 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_245.png filter=lfs diff=lfs merge=lfs -text
|
| 184 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_246.png filter=lfs diff=lfs merge=lfs -text
|
| 185 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_247.png filter=lfs diff=lfs merge=lfs -text
|
| 186 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_248.png filter=lfs diff=lfs merge=lfs -text
|
| 187 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_249.png filter=lfs diff=lfs merge=lfs -text
|
| 188 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_250.png filter=lfs diff=lfs merge=lfs -text
|
| 189 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_251.png filter=lfs diff=lfs merge=lfs -text
|
| 190 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_252.png filter=lfs diff=lfs merge=lfs -text
|
| 191 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_253.png filter=lfs diff=lfs merge=lfs -text
|
| 192 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_254.png filter=lfs diff=lfs merge=lfs -text
|
| 193 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_255.png filter=lfs diff=lfs merge=lfs -text
|
| 194 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_256.png filter=lfs diff=lfs merge=lfs -text
|
| 195 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_257.png filter=lfs diff=lfs merge=lfs -text
|
| 196 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_258.png filter=lfs diff=lfs merge=lfs -text
|
| 197 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_259.png filter=lfs diff=lfs merge=lfs -text
|
| 198 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_260.png filter=lfs diff=lfs merge=lfs -text
|
| 199 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_261.png filter=lfs diff=lfs merge=lfs -text
|
| 200 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_262.png filter=lfs diff=lfs merge=lfs -text
|
| 201 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_263.png filter=lfs diff=lfs merge=lfs -text
|
| 202 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_264.png filter=lfs diff=lfs merge=lfs -text
|
| 203 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_265.png filter=lfs diff=lfs merge=lfs -text
|
| 204 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_266.png filter=lfs diff=lfs merge=lfs -text
|
| 205 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_267.png filter=lfs diff=lfs merge=lfs -text
|
| 206 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_268.png filter=lfs diff=lfs merge=lfs -text
|
| 207 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_269.png filter=lfs diff=lfs merge=lfs -text
|
| 208 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_54.png filter=lfs diff=lfs merge=lfs -text
|
| 209 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_55.png filter=lfs diff=lfs merge=lfs -text
|
| 210 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_56.png filter=lfs diff=lfs merge=lfs -text
|
| 211 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_57.png filter=lfs diff=lfs merge=lfs -text
|
| 212 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_58.png filter=lfs diff=lfs merge=lfs -text
|
| 213 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_59.png filter=lfs diff=lfs merge=lfs -text
|
| 214 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_60.png filter=lfs diff=lfs merge=lfs -text
|
| 215 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_61.png filter=lfs diff=lfs merge=lfs -text
|
| 216 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_62.png filter=lfs diff=lfs merge=lfs -text
|
| 217 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_63.png filter=lfs diff=lfs merge=lfs -text
|
| 218 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_64.png filter=lfs diff=lfs merge=lfs -text
|
| 219 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_65.png filter=lfs diff=lfs merge=lfs -text
|
| 220 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_66.png filter=lfs diff=lfs merge=lfs -text
|
| 221 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_67.png filter=lfs diff=lfs merge=lfs -text
|
| 222 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_68.png filter=lfs diff=lfs merge=lfs -text
|
| 223 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_69.png filter=lfs diff=lfs merge=lfs -text
|
| 224 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_70.png filter=lfs diff=lfs merge=lfs -text
|
| 225 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_71.png filter=lfs diff=lfs merge=lfs -text
|
| 226 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_72.png filter=lfs diff=lfs merge=lfs -text
|
| 227 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_73.png filter=lfs diff=lfs merge=lfs -text
|
| 228 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_74.png filter=lfs diff=lfs merge=lfs -text
|
| 229 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_75.png filter=lfs diff=lfs merge=lfs -text
|
| 230 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_76.png filter=lfs diff=lfs merge=lfs -text
|
| 231 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_77.png filter=lfs diff=lfs merge=lfs -text
|
| 232 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_78.png filter=lfs diff=lfs merge=lfs -text
|
| 233 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_79.png filter=lfs diff=lfs merge=lfs -text
|
| 234 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_80.png filter=lfs diff=lfs merge=lfs -text
|
| 235 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_81.png filter=lfs diff=lfs merge=lfs -text
|
| 236 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_82.png filter=lfs diff=lfs merge=lfs -text
|
| 237 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_83.png filter=lfs diff=lfs merge=lfs -text
|
| 238 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_84.png filter=lfs diff=lfs merge=lfs -text
|
| 239 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_85.png filter=lfs diff=lfs merge=lfs -text
|
| 240 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_86.png filter=lfs diff=lfs merge=lfs -text
|
| 241 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_87.png filter=lfs diff=lfs merge=lfs -text
|
| 242 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_88.png filter=lfs diff=lfs merge=lfs -text
|
| 243 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_89.png filter=lfs diff=lfs merge=lfs -text
|
| 244 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_90.png filter=lfs diff=lfs merge=lfs -text
|
| 245 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_91.png filter=lfs diff=lfs merge=lfs -text
|
| 246 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_92.png filter=lfs diff=lfs merge=lfs -text
|
| 247 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_93.png filter=lfs diff=lfs merge=lfs -text
|
| 248 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_94.png filter=lfs diff=lfs merge=lfs -text
|
| 249 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_95.png filter=lfs diff=lfs merge=lfs -text
|
| 250 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_96.png filter=lfs diff=lfs merge=lfs -text
|
| 251 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_97.png filter=lfs diff=lfs merge=lfs -text
|
| 252 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_98.png filter=lfs diff=lfs merge=lfs -text
|
| 253 |
+
third_party/GVHMR/work_dirs/vitpose_finetune/20251226_182315/vis_data/vis_image/val_img_99.png filter=lfs diff=lfs merge=lfs -text
|
| 254 |
+
third_party/hamer/example_data/test1.jpg filter=lfs diff=lfs merge=lfs -text
|
| 255 |
+
third_party/hamer/example_data/test4.jpg filter=lfs diff=lfs merge=lfs -text
|
| 256 |
+
third_party/hamer/example_data/test5.jpg filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
dataset-generator/
|
| 2 |
+
out/
|
| 3 |
+
__pycache__/
|
| 4 |
+
*.pyc
|
| 5 |
+
outputs/
|
| 6 |
+
out/
|
| 7 |
+
__pycache__/
|
| 8 |
+
*.pyc
|
| 9 |
+
processed_dataset/
|
| 10 |
+
mmpose/
|
| 11 |
+
gvhmr.egg-info/
|
| 12 |
+
Grounded-SAM-2/
|
| 13 |
+
.cache/
|
| 14 |
+
third-party/
|
| 15 |
+
assets/
|
| 16 |
+
*.mp4
|
LICENSE
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
NVIDIA License
|
| 2 |
+
|
| 3 |
+
1. Definitions
|
| 4 |
+
|
| 5 |
+
“Licensor” means any person or entity that distributes its Work.
|
| 6 |
+
“Work” means (a) the original work of authorship made available under this license, which may include software, documentation, or other files, and (b) any additions to or derivative works thereof that are made available under this license.
|
| 7 |
+
The terms “reproduce,” “reproduction,” “derivative works,” and “distribution” have the meaning as provided under U.S. copyright law; provided, however, that for the purposes of this license, derivative works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work.
|
| 8 |
+
Works are “made available” under this license by including in or with the Work either (a) a copyright notice referencing the applicability of this license to the Work, or (b) a copy of this license.
|
| 9 |
+
|
| 10 |
+
2. License Grant
|
| 11 |
+
|
| 12 |
+
2.1 Copyright Grant. Subject to the terms and conditions of this license, each Licensor grants to you a perpetual, worldwide, non-exclusive, royalty-free, copyright license to use, reproduce, prepare derivative works of, publicly display, publicly perform, sublicense and distribute its Work and any resulting derivative works in any form.
|
| 13 |
+
|
| 14 |
+
3. Limitations
|
| 15 |
+
|
| 16 |
+
3.1 Redistribution. You may reproduce or distribute the Work only if (a) you do so under this license, (b) you include a complete copy of this license with your distribution, and (c) you retain without modification any copyright, patent, trademark, or attribution notices that are present in the Work.
|
| 17 |
+
|
| 18 |
+
3.2 Derivative Works. You may specify that additional or different terms apply to the use, reproduction, and distribution of your derivative works of the Work (“Your Terms”) only if (a) Your Terms provide that the use limitation in Section 3.3 applies to your derivative works, and (b) you identify the specific derivative works that are subject to Your Terms. Notwithstanding Your Terms, this license (including the redistribution requirements in Section 3.1) will continue to apply to the Work itself.
|
| 19 |
+
|
| 20 |
+
3.3 Use Limitation. The Work and any derivative works thereof only may be used or intended for use non-commercially. Notwithstanding the foregoing, NVIDIA Corporation and its affiliates may use the Work and any derivative works commercially. As used herein, “non-commercially” means for non-commercial academic purposes only.
|
| 21 |
+
|
| 22 |
+
3.4 Patent Claims. If you bring or threaten to bring a patent claim against any Licensor (including any claim, cross-claim or counterclaim in a lawsuit) to enforce any patents that you allege are infringed by any Work, then your rights under this license from such Licensor (including the grant in Section 2.1) will terminate immediately.
|
| 23 |
+
|
| 24 |
+
3.5 Trademarks. This license does not grant any rights to use any Licensor’s or its affiliates’ names, logos, or trademarks, except as necessary to reproduce the notices described in this license.
|
| 25 |
+
|
| 26 |
+
3.6 Termination. If you violate any term of this license, then your rights under this license (including the grant in Section 2.1) will terminate immediately.
|
| 27 |
+
|
| 28 |
+
4. Disclaimer of Warranty.
|
| 29 |
+
|
| 30 |
+
THE WORK IS PROVIDED “AS IS” WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WARRANTIES OR CONDITIONS OF
|
| 31 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR NON-INFRINGEMENT. YOU BEAR THE RISK OF UNDERTAKING ANY ACTIVITIES UNDER THIS LICENSE.
|
| 32 |
+
|
| 33 |
+
5. Limitation of Liability.
|
| 34 |
+
|
| 35 |
+
EXCEPT AS PROHIBITED BY APPLICABLE LAW, IN NO EVENT AND UNDER NO LEGAL THEORY, WHETHER IN TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE SHALL ANY LICENSOR BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATED TO THIS LICENSE, THE USE OR INABILITY TO USE THE WORK (INCLUDING BUT NOT LIMITED TO LOSS OF GOODWILL, BUSINESS INTERRUPTION, LOST PROFITS OR DATA, COMPUTER FAILURE OR MALFUNCTION, OR ANY OTHER DAMAGES OR LOSSES), EVEN IF THE LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
| 36 |
+
|
README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<p align="center">
|
| 2 |
+
<h1 align="center"> GEM: A Generalist Model for Human Motion</h1>
|
| 3 |
+
<p align="center">
|
| 4 |
+
<a href="https://jeffli.site/"><strong>Jiefeng Li</strong></a>
|
| 5 |
+
·
|
| 6 |
+
<a href="https://www.jinkuncao.com/"><strong>Jinkun Cao</strong></a>
|
| 7 |
+
·
|
| 8 |
+
<a href="https://cs.stanford.edu/~haotianz/"><strong>Haotian Zhang</strong></a>
|
| 9 |
+
·
|
| 10 |
+
<a href="https://davrempe.github.io/"><strong>Davis Rempe</strong></a>
|
| 11 |
+
·
|
| 12 |
+
<a href="https://jankautz.com/"><strong>Jan Kautz</strong></a>
|
| 13 |
+
·
|
| 14 |
+
<a href="https://www.umariqbal.info/"><strong>Umar Iqbal</strong></a>
|
| 15 |
+
·
|
| 16 |
+
<a href="https://ye-yuan.com/"><strong>Ye Yuan</strong></a>
|
| 17 |
+
</p>
|
| 18 |
+
<h2 align="center">ICCV 2025 (Highlight)</h2>
|
| 19 |
+
<div align="center">
|
| 20 |
+
<img src="./assets/teaser.png" alt="Logo" width="100%">
|
| 21 |
+
</div>
|
| 22 |
+
</p>
|
| 23 |
+
<p align="center">
|
| 24 |
+
<a href="https://research.nvidia.com/labs/dair/gem/"><img src="https://img.shields.io/badge/Project-Page-0099cc"></a>
|
| 25 |
+
<a href="https://arxiv.org/abs/2505.01425"><img src="https://img.shields.io/badge/arXiv-2505.01425-b31b1b.svg"></a>
|
| 26 |
+
|
| 27 |
+
</p>
|
| 28 |
+
|
| 29 |
+
**GEM** is a generalist model for human motion that handles multiple tasks with a single model, supporting diverse conditioning signals including video, keypoints, text, audio, and 3D keyframes.
|
| 30 |
+
|
| 31 |
+
---
|
| 32 |
+
|
| 33 |
+
## 📰 News
|
| 34 |
+
- **[December 2025]** 📢 GENMO has been renamed to **GEM**.
|
| 35 |
+
- **[October 2025]** 📢 The **GEM** codebase is **released!**
|
| 36 |
+
Stay tuned for the pretrained models and evaluation scripts.
|
| 37 |
+
Follow the [project page](https://research.nvidia.com/labs/dair/gem/) for updates and announcements.
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
---
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
## 🚀 Highlights
|
| 44 |
+
|
| 45 |
+
GEM introduces a **unified generative framework** that connects motion estimation and generation through shared objectives.
|
| 46 |
+
|
| 47 |
+
- **Unified framework:** Reframes motion estimation as *constrained generation*, allowing a single model to perform both tasks.
|
| 48 |
+
- **Regression × Diffusion synergy:** Combines the accuracy of regression models with the diversity of diffusion-based generation.
|
| 49 |
+
- **Estimation-guided training:** Trains effectively on in-the-wild datasets using only 2D or textual supervision.
|
| 50 |
+
- **Multimodal conditioning:** Supports video, text, audio, 2D/3D keyframes, or even time-varying mixed inputs (e.g., video → text → video).
|
| 51 |
+
- **Arbitrary-length motion:** Generates continuous, coherent sequences of any duration in one diffusion pass.
|
| 52 |
+
- **State-of-the-art performance:** Achieves leading results on diverse motion estimation and generation benchmarks.
|
| 53 |
+
|
| 54 |
+
For more details, visit the **[GEM project page →](https://research.nvidia.com/labs/dair/gem/)**
|
| 55 |
+
|
| 56 |
+
---
|
| 57 |
+
|
| 58 |
+
### Pretrained Models
|
| 59 |
+
You can download pretrained models from [Google Drive](https://drive.google.com/file/d/1b1E84G7S0h2n5o0RmrcmKOhRKukOjgsJ/view?usp=sharing).
|
| 60 |
+
|
| 61 |
+
## 📖 Paper & Citation
|
| 62 |
+
|
| 63 |
+
**Paper:**
|
| 64 |
+
[GENMO: A GENeralist Model for Human MOtion](https://arxiv.org/abs/2505.01425)
|
| 65 |
+
*Jiefeng Li, Jinkun Cao, Haotian Zhang, Davis Rempe, Jan Kautz, Umar Iqbal, Ye Yuan*
|
| 66 |
+
ICCV, 2025
|
| 67 |
+
|
| 68 |
+
**BibTeX:**
|
| 69 |
+
```bibtex
|
| 70 |
+
@inproceedings{genmo2025,
|
| 71 |
+
title = {GENMO: A GENeralist Model for Human MOtion},
|
| 72 |
+
author = {Li, Jiefeng and Cao, Jinkun and Zhang, Haotian and Rempe, Davis and Kautz, Jan and Iqbal, Umar and Yuan, Ye},
|
| 73 |
+
booktitle = {Proceedings of the IEEE/CVF International Conference on Computer Vision (ICCV)},
|
| 74 |
+
year = {2025}
|
| 75 |
+
}
|
REPROCESS_AND_TEST.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Quick Reprocess and Test Instructions
|
| 2 |
+
|
| 3 |
+
## Summary of Changes
|
| 4 |
+
|
| 5 |
+
I've fixed the **rotation computation order** issue in `process_dataset.py`:
|
| 6 |
+
|
| 7 |
+
### The Problem
|
| 8 |
+
- Old: Compute relative rotation in Unity space, then convert to CV
|
| 9 |
+
- Issue: This breaks GENMO's expected formula `R_c = R_w2c @ R_pel_w`
|
| 10 |
+
|
| 11 |
+
### The Fix
|
| 12 |
+
- New: Convert rotations to CV **first**, then compute relative rotation
|
| 13 |
+
- This matches GENMO's training data convention
|
| 14 |
+
|
| 15 |
+
## Step-by-Step Instructions
|
| 16 |
+
|
| 17 |
+
### 1. Clean Old Processed Data
|
| 18 |
+
```bash
|
| 19 |
+
cd /root/miko/puni/train/PromptHMR/GENMO
|
| 20 |
+
rm -rf processed_dataset/genmo_features/*.pt
|
| 21 |
+
```
|
| 22 |
+
|
| 23 |
+
### 2. Reprocess Your Dataset
|
| 24 |
+
```bash
|
| 25 |
+
# Replace paths as needed
|
| 26 |
+
python third_party/GVHMR/tools/demo/process_dataset.py \
|
| 27 |
+
--input /path/to/your/unity_export \
|
| 28 |
+
--output processed_dataset \
|
| 29 |
+
--genmo --vitpose --smplx \
|
| 30 |
+
--consistency_check \
|
| 31 |
+
--consistency_check_frames 5
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
**Expected output:**
|
| 35 |
+
- `[Kabsch] Frame 0 consistency: Rotation err = 0.00°, Translation err = <0.1m`
|
| 36 |
+
- Processing should complete without errors
|
| 37 |
+
|
| 38 |
+
### 3. Run Diagnosis
|
| 39 |
+
```bash
|
| 40 |
+
python diagnose_data.py
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
**Expected results (V2 fix):**
|
| 44 |
+
```
|
| 45 |
+
In-camera orientation errors (mean ± std):
|
| 46 |
+
Yaw: <5.00° ± <2.00° (was 9.44°)
|
| 47 |
+
Pitch: <5.00° ± <2.00° (was 10.95°)
|
| 48 |
+
Roll: <5.00° ± <2.00° (was 168.77° ← THE BUG!)
|
| 49 |
+
|
| 50 |
+
World orientation errors (mean ± std):
|
| 51 |
+
Yaw: <5.00° ± <2.00° (was 55.10°)
|
| 52 |
+
Pitch: <5.00° ± <2.00° (was 4.12°)
|
| 53 |
+
Roll: <5.00° ± <2.00° (was 3.65°)
|
| 54 |
+
|
| 55 |
+
Body pose error: <10.00° ± <20.00° (max: <100°)
|
| 56 |
+
```
|
| 57 |
+
|
| 58 |
+
### 4. If Errors Are Still High...
|
| 59 |
+
|
| 60 |
+
The rotation fix addresses the **rotation computation order**, but if errors persist, check:
|
| 61 |
+
|
| 62 |
+
#### A. Body Pose Export
|
| 63 |
+
Your Unity export's `smplx_pose` might have issues. Check:
|
| 64 |
+
```bash
|
| 65 |
+
# Test if body_pose matches between Unity and processed data
|
| 66 |
+
python test_single_frame.py
|
| 67 |
+
```
|
| 68 |
+
|
| 69 |
+
#### B. SMPL Model Mismatch
|
| 70 |
+
GENMO uses `supermotion_v437coco17`. Verify your Unity uses the same:
|
| 71 |
+
- Check betas (should be 10D, matching `shape.npz`)
|
| 72 |
+
- Check body_pose structure (should be 63D = 21 joints × 3)
|
| 73 |
+
|
| 74 |
+
#### C. Coordinate System Issues
|
| 75 |
+
If roll is exactly 180° off, you might need the Z-180° fix after all (but only for specific camera setups).
|
| 76 |
+
|
| 77 |
+
## What Changed in process_dataset.py
|
| 78 |
+
|
| 79 |
+
### Line 267-281: Incam Rotation
|
| 80 |
+
```python
|
| 81 |
+
# OLD (BROKEN):
|
| 82 |
+
R_rel_unity = R_cam_w.T @ R_pel_w
|
| 83 |
+
R_cv = C @ R_rel_unity @ C
|
| 84 |
+
|
| 85 |
+
# NEW (FIXED):
|
| 86 |
+
R_cam_w_cv = C @ R_cam_w_unity @ C
|
| 87 |
+
R_w2c_cv = R_cam_w_cv.T
|
| 88 |
+
R_pel_w_cv = C @ R_pel_w_unity @ C
|
| 89 |
+
R_pel_c_cv = R_w2c_cv @ R_pel_w_cv # GENMO's formula!
|
| 90 |
+
```
|
| 91 |
+
|
| 92 |
+
### Line 602-614: World Rotation
|
| 93 |
+
```python
|
| 94 |
+
# OLD: Recompute from Unity quaternions
|
| 95 |
+
# NEW: Use pre-converted CV rotations
|
| 96 |
+
R_c2w_cv = p['R_w2c_cv'].T
|
| 97 |
+
R_pelvis_w_cv = R_c2w_cv @ R_pelvis_c_cv
|
| 98 |
+
```
|
| 99 |
+
|
| 100 |
+
### Line 665-671: Camera Matrix
|
| 101 |
+
```python
|
| 102 |
+
# OLD: Convert Unity T_wc with C4 @ T @ C4
|
| 103 |
+
# NEW: Use pre-computed R_w2c_cv
|
| 104 |
+
cam_T_w2c_cv[:3, :3] = p["R_w2c_cv"]
|
| 105 |
+
```
|
| 106 |
+
|
| 107 |
+
## Training
|
| 108 |
+
|
| 109 |
+
After reprocessing with the fix, training should:
|
| 110 |
+
- ✅ Start with loss ~1-5 (not 12)
|
| 111 |
+
- ✅ Decrease steadily (not explode to 100+)
|
| 112 |
+
- ✅ Converge to ~0.5-2.0 after sufficient epochs
|
| 113 |
+
|
| 114 |
+
If loss still explodes:
|
| 115 |
+
1. Check learning rate (might be too high for fine-tuning)
|
| 116 |
+
2. Check data augmentation settings
|
| 117 |
+
3. Verify batch size matches pretrained model's training setup
|
| 118 |
+
|
| 119 |
+
## Files Modified
|
| 120 |
+
|
| 121 |
+
1. [process_dataset.py](third_party/GVHMR/tools/demo/process_dataset.py)
|
| 122 |
+
- Lines 267-281: Fixed incam rotation derivation
|
| 123 |
+
- Lines 306-318: Added R_w2c_cv to return dict
|
| 124 |
+
- Lines 602-614: Use pre-converted rotations
|
| 125 |
+
- Lines 665-671: Use pre-computed camera matrix
|
| 126 |
+
|
| 127 |
+
## Next Steps
|
| 128 |
+
|
| 129 |
+
1. ✅ Reprocess dataset
|
| 130 |
+
2. ✅ Verify diagnosis shows <5° errors
|
| 131 |
+
3. ✅ Start training
|
| 132 |
+
4. 📊 Monitor loss curve (should decrease, not explode)
|
| 133 |
+
|
| 134 |
+
---
|
| 135 |
+
|
| 136 |
+
**Quick Check**: If `diagnose_data.py` still shows 168° roll error after reprocessing, the changes didn't apply. Check:
|
| 137 |
+
- Did you edit the correct `process_dataset.py` file?
|
| 138 |
+
- Did you delete old `.pt` files before reprocessing?
|
| 139 |
+
- Did the reprocessing script complete without errors?
|
ROTATION_FIX_SUMMARY.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Unity Dataset Rotation Fix - Summary
|
| 2 |
+
|
| 3 |
+
## Problem Identified
|
| 4 |
+
|
| 5 |
+
Your training loss was exploding (12 → 100+) because of a **180° rotation mismatch** between your processed data and the pretrained GENMO model's expected convention.
|
| 6 |
+
|
| 7 |
+
### Diagnosis Results (Before Fix)
|
| 8 |
+
- **In-camera roll error: 348.31°** ≈ -11.87° (180° flip issue)
|
| 9 |
+
- **World yaw error: 32.81°**
|
| 10 |
+
- **Body pose max error: 163.37°**
|
| 11 |
+
- **Training loss: Exploding from 12 to 100+**
|
| 12 |
+
|
| 13 |
+
### Root Cause
|
| 14 |
+
The Z-180° rotation fix in [process_dataset.py:276](third_party/GVHMR/tools/demo/process_dataset.py#L276) was being applied during data processing, but the pretrained GENMO model was trained on data **without** this fix. This created a systematic rotation offset.
|
| 15 |
+
|
| 16 |
+
## Changes Made
|
| 17 |
+
|
| 18 |
+
### 1. Removed Z-180° Fix from Incam Rotation (Line 273-278)
|
| 19 |
+
```python
|
| 20 |
+
# OLD (BROKEN):
|
| 21 |
+
R_final = R_cv @ R.from_euler("z", 180, degrees=True).as_matrix()
|
| 22 |
+
global_orient_aa = R.from_matrix(R_final).as_rotvec()
|
| 23 |
+
|
| 24 |
+
# NEW (FIXED):
|
| 25 |
+
global_orient_aa = R.from_matrix(R_cv).as_rotvec()
|
| 26 |
+
```
|
| 27 |
+
|
| 28 |
+
### 2. Removed Z-180° Fix from World Rotation (Line 593-611)
|
| 29 |
+
```python
|
| 30 |
+
# OLD (BROKEN):
|
| 31 |
+
fix_rot = R.from_euler("z", 180, degrees=True).as_matrix()
|
| 32 |
+
R_cam_w_cv = fix_rot @ (C @ R_cam_w_unity @ C)
|
| 33 |
+
pelvis_pos_w_cv = fix_rot @ pos_cv_raw
|
| 34 |
+
|
| 35 |
+
# NEW (FIXED):
|
| 36 |
+
R_cam_w_cv = C @ R_cam_w_unity @ C
|
| 37 |
+
pelvis_pos_w_cv = pos_cv_raw
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
### 3. Removed Z-180° Fix from Camera Matrix (Line 662-667)
|
| 41 |
+
```python
|
| 42 |
+
# OLD (BROKEN):
|
| 43 |
+
cam_T_wc_cv = fix_mat @ (C4 @ cam_T_wc @ C4)
|
| 44 |
+
|
| 45 |
+
# NEW (FIXED):
|
| 46 |
+
cam_T_wc_cv = C4 @ cam_T_wc @ C4
|
| 47 |
+
```
|
| 48 |
+
|
| 49 |
+
## Verification Steps
|
| 50 |
+
|
| 51 |
+
### 1. Reprocess Your Dataset
|
| 52 |
+
```bash
|
| 53 |
+
# Delete old processed data
|
| 54 |
+
rm -rf processed_dataset/genmo_features/*.pt
|
| 55 |
+
|
| 56 |
+
# Reprocess with the fixed script
|
| 57 |
+
python third_party/GVHMR/tools/demo/process_dataset.py \
|
| 58 |
+
--input path/to/unity_export \
|
| 59 |
+
--output processed_dataset \
|
| 60 |
+
--genmo --vitpose --smplx \
|
| 61 |
+
--consistency_check
|
| 62 |
+
```
|
| 63 |
+
|
| 64 |
+
### 2. Run Diagnosis Again
|
| 65 |
+
```bash
|
| 66 |
+
python diagnose_data.py
|
| 67 |
+
```
|
| 68 |
+
|
| 69 |
+
### Expected Results (After Fix)
|
| 70 |
+
- **In-camera roll error: <10°** (instead of 348°)
|
| 71 |
+
- **World orientation errors: <5°** for all axes
|
| 72 |
+
- **Body pose error: <10° mean**
|
| 73 |
+
- **Training loss: Should stabilize around 0.5-2.0**
|
| 74 |
+
|
| 75 |
+
### 3. Resume Training
|
| 76 |
+
```bash
|
| 77 |
+
# Your training should now converge properly
|
| 78 |
+
python train.py --config configs/genmo_lg.yaml
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
## Why Kabsch Consistency Check Still Passed
|
| 82 |
+
|
| 83 |
+
The Kabsch alignment check (0.00° error) only verifies **internal geometric consistency** between incam and world SMPL parameters using your exported camera transforms. It does NOT check if your data matches the pretrained model's convention.
|
| 84 |
+
|
| 85 |
+
Think of it like this:
|
| 86 |
+
- ✅ Your Unity → SMPL conversion is geometrically correct
|
| 87 |
+
- ❌ But the coordinate convention doesn't match GENMO's training data
|
| 88 |
+
|
| 89 |
+
## Additional Notes
|
| 90 |
+
|
| 91 |
+
### If Errors Persist After Reprocessing
|
| 92 |
+
|
| 93 |
+
1. **Check body pose errors**: If still >20° mean, your Unity export's `smplx_pose` might have issues
|
| 94 |
+
2. **Check world translation**: Should be normalized (first frame at origin ± offset)
|
| 95 |
+
3. **Verify Unity quaternion order**: Should be XYZW (not WXYZ)
|
| 96 |
+
|
| 97 |
+
### Understanding the Z-180° Fix
|
| 98 |
+
|
| 99 |
+
The Z-180° rotation is sometimes needed when converting between:
|
| 100 |
+
- Unity's left-handed Y-up coordinate system
|
| 101 |
+
- CV convention's right-handed Y-down system
|
| 102 |
+
|
| 103 |
+
However, the pretrained GENMO model was trained with data that did NOT apply this fix after the basic Unity→CV conversion (Y-flip via `C = diag([1, -1, 1])`). Your processing pipeline was applying an extra 180° rotation that the model wasn't expecting.
|
| 104 |
+
|
| 105 |
+
## Modified Files
|
| 106 |
+
|
| 107 |
+
1. [third_party/GVHMR/tools/demo/process_dataset.py](third_party/GVHMR/tools/demo/process_dataset.py)
|
| 108 |
+
- Line 273-278: Removed Z-180° from incam rotation
|
| 109 |
+
- Line 593-611: Removed Z-180° from world rotation derivation
|
| 110 |
+
- Line 662-667: Removed Z-180° from camera matrices
|
| 111 |
+
|
| 112 |
+
## Next Steps
|
| 113 |
+
|
| 114 |
+
1. ✅ Reprocess dataset with fixed script
|
| 115 |
+
2. ✅ Verify with `diagnose_data.py` (should show <10° errors)
|
| 116 |
+
3. ✅ Resume training (loss should stabilize)
|
| 117 |
+
4. 🎯 If training still diverges, check learning rate and batch size
|
| 118 |
+
|
| 119 |
+
---
|
| 120 |
+
|
| 121 |
+
**tl;dr**: The pretrained model expects rotations without Z-180° fix. Removed the fix from 3 places in process_dataset.py. Reprocess your data and training should converge.
|
ROTATION_FIX_V2_SUMMARY.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Unity Dataset Rotation Fix V2 - The Real Issue
|
| 2 |
+
|
| 3 |
+
## Problem Evolution
|
| 4 |
+
|
| 5 |
+
### First Attempt Results (After removing Z-180° fix)
|
| 6 |
+
- **In-camera roll error: 168.77°** (improved from 348°, but still wrong)
|
| 7 |
+
- **World yaw error: 55.10°**
|
| 8 |
+
- Still not matching GENMO's expected convention
|
| 9 |
+
|
| 10 |
+
## Root Cause - Matrix Multiplication Order
|
| 11 |
+
|
| 12 |
+
After deep investigation of GENMO's codebase, the issue was found in **how we compute the incam rotation**:
|
| 13 |
+
|
| 14 |
+
### GENMO's Expected Formula
|
| 15 |
+
From `/third_party/GVHMR/hmr4d/utils/geo/hmr_global.py:100`:
|
| 16 |
+
```python
|
| 17 |
+
R_c = matrix_to_axis_angle(R_w2c @ R_w) # Camera rotation = R_w2c @ World_rotation
|
| 18 |
+
```
|
| 19 |
+
|
| 20 |
+
### Our Old Method (WRONG)
|
| 21 |
+
```python
|
| 22 |
+
# Step 1: Compute relative rotation in Unity space
|
| 23 |
+
R_rel_unity = R_cam_w_unity.T @ R_pel_w_unity
|
| 24 |
+
|
| 25 |
+
# Step 2: Convert to CV
|
| 26 |
+
R_cv = C @ R_rel_unity @ C
|
| 27 |
+
|
| 28 |
+
# Problem: Coordinate conversion happens AFTER computing relative rotation
|
| 29 |
+
# This breaks the math because rotation composition is not commutative with basis changes
|
| 30 |
+
```
|
| 31 |
+
|
| 32 |
+
### New Method (CORRECT)
|
| 33 |
+
```python
|
| 34 |
+
# Step 1: Convert BOTH rotations to CV convention FIRST
|
| 35 |
+
R_cam_w_cv = C @ R_cam_w_unity @ C # Camera-to-world in CV
|
| 36 |
+
R_pel_w_cv = C @ R_pel_w_unity @ C # Pelvis-to-world in CV
|
| 37 |
+
|
| 38 |
+
# Step 2: Compute relative rotation IN CV space
|
| 39 |
+
R_w2c_cv = R_cam_w_cv.T # World-to-camera in CV
|
| 40 |
+
R_pel_c_cv = R_w2c_cv @ R_pel_w_cv # GENMO's formula in CV space
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
## Why Order Matters
|
| 44 |
+
|
| 45 |
+
The key insight: **R @ (C @ M @ C) ≠ C @ (R @ M) @ C** when changing coordinate systems.
|
| 46 |
+
|
| 47 |
+
When you:
|
| 48 |
+
1. ❌ Compute rotation in Unity space, then convert to CV → Wrong
|
| 49 |
+
2. ✅ Convert rotations to CV, then compute relative rotation → Correct
|
| 50 |
+
|
| 51 |
+
This is because rotation composition depends on the coordinate basis. The formula `R_w2c @ R_pel_w` assumes BOTH matrices are in the SAME coordinate system (CV).
|
| 52 |
+
|
| 53 |
+
## Changes Made
|
| 54 |
+
|
| 55 |
+
### 1. Fixed Incam Rotation Computation (Lines 267-281)
|
| 56 |
+
|
| 57 |
+
```python
|
| 58 |
+
# Get raw Unity quaternions
|
| 59 |
+
cam_rot_w_quat = np.array(row["cam_rot_world"], dtype=np.float64)
|
| 60 |
+
R_cam_w_unity = R.from_quat(cam_rot_w_quat).as_matrix()
|
| 61 |
+
pel_rot_w_quat = np.array(row["pelvis_rot_world"], dtype=np.float64)
|
| 62 |
+
R_pel_w_unity = R.from_quat(pel_rot_w_quat).as_matrix()
|
| 63 |
+
|
| 64 |
+
# Convert to CV convention FIRST, then compute relative rotation
|
| 65 |
+
# Model expects: global_orient_c = R_w2c @ R_pel_w (in CV convention)
|
| 66 |
+
R_cam_w_cv = C @ R_cam_w_unity @ C # Camera-to-world in CV
|
| 67 |
+
R_w2c_cv = R_cam_w_cv.T # World-to-camera in CV
|
| 68 |
+
R_pel_w_cv = C @ R_pel_w_unity @ C # Pelvis-to-world in CV
|
| 69 |
+
|
| 70 |
+
# Compute incam rotation in CV convention
|
| 71 |
+
R_pel_c_cv = R_w2c_cv @ R_pel_w_cv # This matches GENMO's formula!
|
| 72 |
+
global_orient_aa = R.from_matrix(R_pel_c_cv).as_rotvec().astype(np.float32)
|
| 73 |
+
```
|
| 74 |
+
|
| 75 |
+
### 2. Updated Return Values to Include CV Rotations (Lines 306-318)
|
| 76 |
+
|
| 77 |
+
```python
|
| 78 |
+
return {
|
| 79 |
+
"global_orient": global_orient_aa,
|
| 80 |
+
"body_pose": body_pose,
|
| 81 |
+
"betas": betas10,
|
| 82 |
+
"R_w2c_cv": R_w2c_cv, # Add for reuse
|
| 83 |
+
"R_pel_w_cv": R_pel_w_cv, # Add for reuse
|
| 84 |
+
...
|
| 85 |
+
}
|
| 86 |
+
```
|
| 87 |
+
|
| 88 |
+
### 3. Fixed World Rotation Derivation (Lines 602-614)
|
| 89 |
+
|
| 90 |
+
```python
|
| 91 |
+
# Use pre-converted rotations from parse_smpl_inputs_from_row
|
| 92 |
+
for p in parsed:
|
| 93 |
+
R_pelvis_c_cv = R.from_rotvec(p['global_orient']).as_matrix()
|
| 94 |
+
R_c2w_cv = p['R_w2c_cv'].T # Camera-to-world (inverse of w2c)
|
| 95 |
+
R_pelvis_w_cv = R_c2w_cv @ R_pelvis_c_cv
|
| 96 |
+
all_go_w.append(R.from_matrix(R_pelvis_w_cv).as_rotvec())
|
| 97 |
+
```
|
| 98 |
+
|
| 99 |
+
### 4. Fixed Camera Matrix Construction (Lines 665-671)
|
| 100 |
+
|
| 101 |
+
```python
|
| 102 |
+
# Use pre-computed CV-convention rotation (not recompute from Unity!)
|
| 103 |
+
cam_T_w2c_cv = np.eye(4, dtype=np.float32)
|
| 104 |
+
cam_T_w2c_cv[:3, :3] = p["R_w2c_cv"].astype(np.float32)
|
| 105 |
+
cam_pos_cv = C @ p["cam_pos_world"]
|
| 106 |
+
cam_T_w2c_cv[:3, 3] = (-p["R_w2c_cv"] @ cam_pos_cv).astype(np.float32)
|
| 107 |
+
```
|
| 108 |
+
|
| 109 |
+
## Verification Steps
|
| 110 |
+
|
| 111 |
+
### 1. Reprocess Dataset
|
| 112 |
+
```bash
|
| 113 |
+
# Clean old data
|
| 114 |
+
rm -rf processed_dataset/genmo_features/*.pt
|
| 115 |
+
|
| 116 |
+
# Reprocess
|
| 117 |
+
python third_party/GVHMR/tools/demo/process_dataset.py \
|
| 118 |
+
--input path/to/unity_export \
|
| 119 |
+
--output processed_dataset \
|
| 120 |
+
--genmo --vitpose --smplx \
|
| 121 |
+
--consistency_check
|
| 122 |
+
```
|
| 123 |
+
|
| 124 |
+
### 2. Run Diagnosis
|
| 125 |
+
```bash
|
| 126 |
+
python diagnose_data.py
|
| 127 |
+
```
|
| 128 |
+
|
| 129 |
+
### Expected Results (After V2 Fix)
|
| 130 |
+
- **In-camera orientation errors: <5°** for all axes (yaw, pitch, roll)
|
| 131 |
+
- **World orientation errors: <5°** for all axes
|
| 132 |
+
- **Body pose mean error: <5°**
|
| 133 |
+
- **World translation error: <0.1m** (excluding the intentional 1.34m Y-offset)
|
| 134 |
+
- **Training loss: Should converge to 0.5-2.0** instead of exploding
|
| 135 |
+
|
| 136 |
+
## Understanding the Math
|
| 137 |
+
|
| 138 |
+
### Why R_w2c @ R_pel_w?
|
| 139 |
+
|
| 140 |
+
Think of applying rotations to a vector:
|
| 141 |
+
1. Start with pelvis-local vector: `v_pelvis`
|
| 142 |
+
2. Rotate to world: `v_world = R_pel_w @ v_pelvis`
|
| 143 |
+
3. Rotate to camera: `v_camera = R_w2c @ v_world`
|
| 144 |
+
4. Combine: `v_camera = R_w2c @ (R_pel_w @ v_pelvis) = (R_w2c @ R_pel_w) @ v_pelvis`
|
| 145 |
+
|
| 146 |
+
So: `R_pel_c = R_w2c @ R_pel_w` (rotation composition follows the transformation chain)
|
| 147 |
+
|
| 148 |
+
### Why Convert to CV First?
|
| 149 |
+
|
| 150 |
+
Because GENMO was trained on data where ALL rotations are in CV convention. If you compute relative rotations in Unity space then convert, the mathematical relationship changes due to the basis transformation.
|
| 151 |
+
|
| 152 |
+
It's like computing `A + B` vs. `f(A) + f(B)` - only works if `f` is linear (which coordinate transforms are for INDIVIDUAL rotations, but NOT for rotation composition).
|
| 153 |
+
|
| 154 |
+
## Modified Files
|
| 155 |
+
|
| 156 |
+
1. [third_party/GVHMR/tools/demo/process_dataset.py](third_party/GVHMR/tools/demo/process_dataset.py)
|
| 157 |
+
- Lines 267-281: Fixed incam rotation (convert to CV FIRST)
|
| 158 |
+
- Lines 306-318: Added R_w2c_cv and R_pel_w_cv to return dict
|
| 159 |
+
- Lines 602-614: Use pre-converted rotations for world derivation
|
| 160 |
+
- Lines 665-671: Use pre-computed R_w2c_cv for camera matrix
|
| 161 |
+
|
| 162 |
+
## Technical Details
|
| 163 |
+
|
| 164 |
+
### Coordinate Systems Involved
|
| 165 |
+
|
| 166 |
+
1. **Unity World**: Left-handed, Y-up
|
| 167 |
+
- Camera: `cam_rot_world` (quaternion XYZW)
|
| 168 |
+
- Pelvis: `pelvis_rot_world` (quaternion XYZW)
|
| 169 |
+
|
| 170 |
+
2. **CV Convention**: Right-handed, Y-down
|
| 171 |
+
- Conversion: `R_cv = C @ R_unity @ C` where `C = diag([1, -1, 1])`
|
| 172 |
+
- Flips Y-axis to convert handedness
|
| 173 |
+
|
| 174 |
+
3. **SMPL**: Uses axis-angle representation (3D vectors)
|
| 175 |
+
- Magnitude = rotation angle (radians)
|
| 176 |
+
- Direction = rotation axis (right-hand rule)
|
| 177 |
+
|
| 178 |
+
### Rotation Representation Chain
|
| 179 |
+
|
| 180 |
+
```
|
| 181 |
+
Unity Quat → Matrix → CV Matrix → Composition → CV Matrix → Axis-Angle
|
| 182 |
+
(XYZW) (3x3) (3x3) (R_w2c@R_w) (3x3) (3D vec)
|
| 183 |
+
```
|
| 184 |
+
|
| 185 |
+
Each step must preserve the rotation semantics in the target coordinate system.
|
| 186 |
+
|
| 187 |
+
## Next Steps
|
| 188 |
+
|
| 189 |
+
1. ✅ Reprocess dataset with V2 fix
|
| 190 |
+
2. ✅ Verify with `diagnose_data.py` (expect <5° errors)
|
| 191 |
+
3. ✅ Resume training
|
| 192 |
+
4. 🎯 Monitor first 1000 steps - loss should decrease steadily
|
| 193 |
+
|
| 194 |
+
---
|
| 195 |
+
|
| 196 |
+
**tl;dr**: The issue was computing relative rotations in Unity space then converting to CV. Fixed by converting BOTH rotations to CV FIRST, then computing `R_pel_c = R_w2c @ R_pel_w` as GENMO expects. This matches the mathematical formula in the trained model.
|
SyntheticRecorder.cs
ADDED
|
@@ -0,0 +1,681 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
using UnityEngine;
|
| 2 |
+
using System;
|
| 3 |
+
using System.IO;
|
| 4 |
+
using System.Collections;
|
| 5 |
+
using System.Collections.Generic;
|
| 6 |
+
using Newtonsoft.Json;
|
| 7 |
+
using UnityEngine.SceneManagement;
|
| 8 |
+
using System.Diagnostics; // Required for FFmpeg Process
|
| 9 |
+
|
| 10 |
+
public class SyntheticRecorder : MonoBehaviour
|
| 11 |
+
{
|
| 12 |
+
// --- CONFIGURATION CLASSES ---
|
| 13 |
+
[System.Serializable]
|
| 14 |
+
public class AvatarConfig
|
| 15 |
+
{
|
| 16 |
+
public string avatarName = "Avatar";
|
| 17 |
+
public GameObject avatarObject;
|
| 18 |
+
[Header("Animation")]
|
| 19 |
+
public Animator animator;
|
| 20 |
+
[Header("Retargeting Link")]
|
| 21 |
+
public HybridPoseCopier retargeter;
|
| 22 |
+
public List<GameObject> extraMeshes = new List<GameObject>();
|
| 23 |
+
public float specificPadding = 40f;
|
| 24 |
+
[Header("Keypoint Markers (COCO-17 order)")]
|
| 25 |
+
public List<Transform> customMarkers = new List<Transform>();
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
// --- JSON STRUCTURES ---
|
| 29 |
+
public class SequenceData { public List<FrameData> frames; }
|
| 30 |
+
public class FrameData { public int i; public float[] p, t, b; public int s; }
|
| 31 |
+
|
| 32 |
+
public class OutputMeta
|
| 33 |
+
{
|
| 34 |
+
public int frame_index;
|
| 35 |
+
public string image_path;
|
| 36 |
+
public string avatar_name;
|
| 37 |
+
public int face_id;
|
| 38 |
+
public int left_hand_id;
|
| 39 |
+
public int right_hand_id;
|
| 40 |
+
public float[] bbox;
|
| 41 |
+
public float[] kpts_2d;
|
| 42 |
+
public int[] kpts_vis;
|
| 43 |
+
public float[] bbox_clip;
|
| 44 |
+
public float[] cam_intrinsics;
|
| 45 |
+
// RAW UNITY TRANSFORMS - Python derives incam/global from these
|
| 46 |
+
public float[] cam_pos_world;
|
| 47 |
+
public float[] cam_rot_world;
|
| 48 |
+
public float[] pelvis_pos_world;
|
| 49 |
+
public float[] pelvis_rot_world;
|
| 50 |
+
// INCAM TRANSLATION (pre-converted to CV Y-flip)
|
| 51 |
+
public float[] smpl_incam_transl;
|
| 52 |
+
public float[] smpl_root_incam_transl;
|
| 53 |
+
public float smpl_root_world_scale;
|
| 54 |
+
public float[] kpts_3d_world;
|
| 55 |
+
public float[] smplx_pose;
|
| 56 |
+
public float[] smplx_betas;
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
[Header("Settings")]
|
| 60 |
+
public string inputFolderPath = "Assets/StreamingAssets";
|
| 61 |
+
public string outputFolder = "C:/Temp/SyntheticDataset";
|
| 62 |
+
public bool startRecordingOnPlay = true;
|
| 63 |
+
public bool showDebugUI = true;
|
| 64 |
+
[Tooltip("If true, saves depth_xxxxx.png files to check what the occlusion camera sees.")]
|
| 65 |
+
public bool saveDebugDepthImages = true;
|
| 66 |
+
|
| 67 |
+
[Header("Video Settings")]
|
| 68 |
+
public string ffmpegPath = "ffmpeg";
|
| 69 |
+
public int frameRate = 30;
|
| 70 |
+
|
| 71 |
+
[Header("Compression (Twitch VOD Simulation)")]
|
| 72 |
+
[Tooltip("Target Bitrate in kbps. 6000 is High Quality 1080p. 2500 is messy 720p.")]
|
| 73 |
+
public int targetBitrateKbps = 2500;
|
| 74 |
+
[Tooltip("GOP (Group of Pictures) size in seconds. Twitch uses 2 seconds.")]
|
| 75 |
+
public float gopSizeSeconds = 2.0f;
|
| 76 |
+
|
| 77 |
+
[Header("Parallel Processing")]
|
| 78 |
+
public int workerId = 0;
|
| 79 |
+
public int totalWorkers = 1;
|
| 80 |
+
|
| 81 |
+
[Header("Sequence Naming")]
|
| 82 |
+
public string sequenceName = "";
|
| 83 |
+
private string _currentInputJsonPath = "";
|
| 84 |
+
|
| 85 |
+
[Header("Occlusion Settings")]
|
| 86 |
+
public float occlusionBias = 0.02f;
|
| 87 |
+
|
| 88 |
+
[Header("References")]
|
| 89 |
+
public GameObject characterRoot;
|
| 90 |
+
public Camera vtuberCamera;
|
| 91 |
+
public SyntheticCameraDriver cameraDriver;
|
| 92 |
+
|
| 93 |
+
[Header("Randomization")]
|
| 94 |
+
public List<AvatarConfig> avatarList = new List<AvatarConfig>();
|
| 95 |
+
public List<string> worldSceneNames = new List<string>();
|
| 96 |
+
public LoadSceneMode worldSceneLoadMode = LoadSceneMode.Additive;
|
| 97 |
+
public bool setLoadedWorldSceneActive = true;
|
| 98 |
+
public string worldMainCameraName = "Main Camera";
|
| 99 |
+
public string spawnPointToken = "SpawnPoint";
|
| 100 |
+
|
| 101 |
+
[Header("Animation Indices")]
|
| 102 |
+
public int faceMaxId = 5;
|
| 103 |
+
public int handsMaxId = 5;
|
| 104 |
+
public int minSwitchFrames = 30;
|
| 105 |
+
public int maxSwitchFrames = 120;
|
| 106 |
+
public string paramFaceIndex = "FaceIndex";
|
| 107 |
+
public string paramLeftHandIndex = "LeftHandIndex";
|
| 108 |
+
public string paramRightHandIndex = "RightHandIndex";
|
| 109 |
+
|
| 110 |
+
[Header("BBOX Accuracy")]
|
| 111 |
+
public bool useBakedSkinnedMeshForBbox = true;
|
| 112 |
+
public int bakedVertexStride = 8;
|
| 113 |
+
|
| 114 |
+
[Header("Calibration")]
|
| 115 |
+
public float movementScale = 1.0f;
|
| 116 |
+
public Vector3 translationOffset = new Vector3(0, 0.05f, 0);
|
| 117 |
+
public Vector3 globalCoordinateCorrection = new Vector3(-90, 180, 0);
|
| 118 |
+
|
| 119 |
+
// --- PRIVATE STATE ---
|
| 120 |
+
private float _activePadding = 40f;
|
| 121 |
+
private SequenceData _data;
|
| 122 |
+
private Transform[] _bones;
|
| 123 |
+
private Transform _pelvisBone;
|
| 124 |
+
private List<Transform> _activeMarkers = new List<Transform>();
|
| 125 |
+
private HybridPoseCopier _activeRetargeter;
|
| 126 |
+
private Transform _activeAvatarRoot = null;
|
| 127 |
+
private Animator _activeAnimator = null;
|
| 128 |
+
private string _activeAvatarName = "";
|
| 129 |
+
private readonly List<Renderer> _activeBboxRenderers = new List<Renderer>();
|
| 130 |
+
private Mesh _bakeMesh;
|
| 131 |
+
private readonly List<Vector3> _bakedVerts = new List<Vector3>(8192);
|
| 132 |
+
private Texture2D _greenTex, _redTex, _occTex;
|
| 133 |
+
private Rect _cachedBbox = new Rect(0, 0, 0, 0);
|
| 134 |
+
private bool _cachedHasBbox = false;
|
| 135 |
+
private int[] _cachedMarkerVis = null;
|
| 136 |
+
private string _currentlyLoadedWorldScene = "";
|
| 137 |
+
|
| 138 |
+
private Shader _autoDepthShader;
|
| 139 |
+
private const int JOINT_COUNT = 22;
|
| 140 |
+
private static readonly string[] BONE_NAMES = {
|
| 141 |
+
"pelvis", "left_hip", "right_hip", "spine1", "left_knee", "right_knee", "spine2",
|
| 142 |
+
"left_ankle", "right_ankle", "spine3", "left_foot", "right_foot", "neck", "left_collar",
|
| 143 |
+
"right_collar", "head", "left_shoulder", "right_shoulder", "left_elbow", "right_elbow",
|
| 144 |
+
"left_wrist", "right_wrist"
|
| 145 |
+
};
|
| 146 |
+
|
| 147 |
+
void Start()
|
| 148 |
+
{
|
| 149 |
+
Screen.SetResolution(1280, 720, FullScreenMode.Windowed);
|
| 150 |
+
|
| 151 |
+
EnsureDepthShaderExists();
|
| 152 |
+
_autoDepthShader = Shader.Find("Custom/AutoLinearDepth");
|
| 153 |
+
if (!_autoDepthShader) UnityEngine.Debug.LogError("Could not load the auto-generated depth shader!");
|
| 154 |
+
|
| 155 |
+
_greenTex = new Texture2D(1, 1); _greenTex.SetPixel(0, 0, Color.green); _greenTex.Apply();
|
| 156 |
+
_redTex = new Texture2D(1, 1); _redTex.SetPixel(0, 0, Color.red); _redTex.Apply();
|
| 157 |
+
_occTex = new Texture2D(1, 1); _occTex.SetPixel(0, 0, new Color(1, 0, 0, 0.5f)); _occTex.Apply();
|
| 158 |
+
|
| 159 |
+
_bakeMesh = new Mesh();
|
| 160 |
+
_bakeMesh.MarkDynamic();
|
| 161 |
+
|
| 162 |
+
if (startRecordingOnPlay)
|
| 163 |
+
StartCoroutine(ProcessBatch());
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
private void EnsureDepthShaderExists()
|
| 167 |
+
{
|
| 168 |
+
string path = "Assets/SyntheticDepth.shader";
|
| 169 |
+
if (File.Exists(path)) return;
|
| 170 |
+
|
| 171 |
+
string shaderCode = @"
|
| 172 |
+
Shader ""Custom/AutoLinearDepth""
|
| 173 |
+
{
|
| 174 |
+
SubShader
|
| 175 |
+
{
|
| 176 |
+
Tags { ""RenderType""="""" ""Queue""=""Geometry"" ""ForceNoShadowCasting""=""True"" }
|
| 177 |
+
Cull Off
|
| 178 |
+
ZWrite On
|
| 179 |
+
ZTest LEqual
|
| 180 |
+
Pass
|
| 181 |
+
{
|
| 182 |
+
CGPROGRAM
|
| 183 |
+
#pragma vertex vert
|
| 184 |
+
#pragma fragment frag
|
| 185 |
+
#include ""UnityCG.cginc""
|
| 186 |
+
struct appdata { float4 vertex : POSITION; };
|
| 187 |
+
struct v2f { float4 pos : SV_POSITION; float depth : TEXCOORD0; };
|
| 188 |
+
v2f vert (appdata v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.depth = -UnityObjectToViewPos(v.vertex).z; return o; }
|
| 189 |
+
float4 frag (v2f i) : SV_Target { return float4(i.depth, 0, 0, 1); }
|
| 190 |
+
ENDCG
|
| 191 |
+
}
|
| 192 |
+
}
|
| 193 |
+
}";
|
| 194 |
+
File.WriteAllText(path, shaderCode);
|
| 195 |
+
#if UNITY_EDITOR
|
| 196 |
+
UnityEditor.AssetDatabase.Refresh();
|
| 197 |
+
#endif
|
| 198 |
+
UnityEngine.Debug.Log("Created Aggressive AutoLinearDepth shader at " + path);
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
private IEnumerator ProcessBatch()
|
| 202 |
+
{
|
| 203 |
+
string fullInputPath = Path.IsPathRooted(inputFolderPath) ? inputFolderPath : Path.Combine(Application.dataPath, "..", inputFolderPath);
|
| 204 |
+
if (!Directory.Exists(fullInputPath)) { UnityEngine.Debug.LogError("Input folder missing"); yield break; }
|
| 205 |
+
|
| 206 |
+
string[] allFiles = Directory.GetFiles(fullInputPath, "*.json");
|
| 207 |
+
Array.Sort(allFiles);
|
| 208 |
+
|
| 209 |
+
List<string> myFiles = new List<string>();
|
| 210 |
+
int safeTotalWorkers = Mathf.Max(1, totalWorkers);
|
| 211 |
+
|
| 212 |
+
for (int i = 0; i < allFiles.Length; i++)
|
| 213 |
+
if (i % safeTotalWorkers == workerId) myFiles.Add(allFiles[i]);
|
| 214 |
+
|
| 215 |
+
foreach (string file in myFiles)
|
| 216 |
+
{
|
| 217 |
+
_currentInputJsonPath = file;
|
| 218 |
+
sequenceName = Path.GetFileNameWithoutExtension(file);
|
| 219 |
+
|
| 220 |
+
Resources.UnloadUnusedAssets();
|
| 221 |
+
System.GC.Collect();
|
| 222 |
+
|
| 223 |
+
yield return StartCoroutine(LoadRandomWorldRoutine());
|
| 224 |
+
|
| 225 |
+
RandomizeAvatarAndGatherRenderers();
|
| 226 |
+
FindAndCacheBones();
|
| 227 |
+
ApplyRandomSpawnPoint(SceneManager.GetActiveScene());
|
| 228 |
+
|
| 229 |
+
yield return StartCoroutine(RecordSingleSequence());
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
#if UNITY_EDITOR
|
| 233 |
+
UnityEditor.EditorApplication.isPlaying = false;
|
| 234 |
+
#else
|
| 235 |
+
Application.Quit();
|
| 236 |
+
#endif
|
| 237 |
+
}
|
| 238 |
+
|
| 239 |
+
private IEnumerator LoadRandomWorldRoutine()
|
| 240 |
+
{
|
| 241 |
+
if (worldSceneNames == null || worldSceneNames.Count == 0) yield break;
|
| 242 |
+
|
| 243 |
+
if (!string.IsNullOrEmpty(_currentlyLoadedWorldScene) && worldSceneLoadMode == LoadSceneMode.Additive)
|
| 244 |
+
{
|
| 245 |
+
AsyncOperation unloadOp = SceneManager.UnloadSceneAsync(_currentlyLoadedWorldScene);
|
| 246 |
+
while (unloadOp != null && !unloadOp.isDone) yield return null;
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
string chosen = worldSceneNames[UnityEngine.Random.Range(0, worldSceneNames.Count)].Trim();
|
| 250 |
+
_currentlyLoadedWorldScene = chosen;
|
| 251 |
+
|
| 252 |
+
AsyncOperation loadOp = SceneManager.LoadSceneAsync(chosen, worldSceneLoadMode);
|
| 253 |
+
while (!loadOp.isDone) yield return null;
|
| 254 |
+
yield return null;
|
| 255 |
+
|
| 256 |
+
Scene loaded = SceneManager.GetSceneByName(chosen);
|
| 257 |
+
if (!loaded.IsValid()) loaded = SceneManager.GetSceneByPath(chosen);
|
| 258 |
+
|
| 259 |
+
if (loaded.IsValid() && loaded.isLoaded)
|
| 260 |
+
{
|
| 261 |
+
if (setLoadedWorldSceneActive) SceneManager.SetActiveScene(loaded);
|
| 262 |
+
BindToWorldMainCameraOrLog(loaded);
|
| 263 |
+
}
|
| 264 |
+
}
|
| 265 |
+
|
| 266 |
+
IEnumerator RecordSingleSequence()
|
| 267 |
+
{
|
| 268 |
+
_data = JsonConvert.DeserializeObject<SequenceData>(File.ReadAllText(_currentInputJsonPath));
|
| 269 |
+
|
| 270 |
+
if (!Directory.Exists(outputFolder)) Directory.CreateDirectory(outputFolder);
|
| 271 |
+
string seqImageDir = Path.Combine(outputFolder, "images", sequenceName);
|
| 272 |
+
if (!Directory.Exists(seqImageDir)) Directory.CreateDirectory(seqImageDir);
|
| 273 |
+
|
| 274 |
+
// --- FFmpeg Setup for VOD SIMULATION ---
|
| 275 |
+
string videoPath = Path.Combine(outputFolder, $"video_{sequenceName}.mp4").Replace("\\", "/");
|
| 276 |
+
|
| 277 |
+
// VOD SIMULATION LOGIC:
|
| 278 |
+
// 1. -b:v {bitrate}k -> Forces the encoder to target a specific bandwidth
|
| 279 |
+
// 2. -maxrate {bitrate}k -> Prevents it from spiking quality during high motion (causes artifacts)
|
| 280 |
+
// 3. -bufsize {bitrate*2}k -> Standard buffer size for streaming
|
| 281 |
+
// 4. -g {gop} -> Sets Keyframe Interval. Twitch uses 2 seconds fixed.
|
| 282 |
+
// 5. -preset ultrafast -> Keeps Unity realtime, but relies on bitrate starvation to cause the artifacts
|
| 283 |
+
|
| 284 |
+
int gopFrames = Mathf.RoundToInt(frameRate * gopSizeSeconds);
|
| 285 |
+
|
| 286 |
+
string ffmpegArgs = $"-y -f rawvideo -vcodec rawvideo -pix_fmt rgb24 " +
|
| 287 |
+
$"-s {Screen.width}x{Screen.height} -r {frameRate} -i - " +
|
| 288 |
+
$"-vf vflip " +
|
| 289 |
+
$"-c:v libx264 " +
|
| 290 |
+
$"-pix_fmt yuv420p " +
|
| 291 |
+
$"-preset ultrafast " +
|
| 292 |
+
$"-b:v {targetBitrateKbps}k -maxrate {targetBitrateKbps}k -bufsize {targetBitrateKbps * 2}k " +
|
| 293 |
+
$"-g {gopFrames} " +
|
| 294 |
+
$"\"{videoPath}\"";
|
| 295 |
+
|
| 296 |
+
ProcessStartInfo psi = new ProcessStartInfo
|
| 297 |
+
{
|
| 298 |
+
FileName = ffmpegPath,
|
| 299 |
+
Arguments = ffmpegArgs,
|
| 300 |
+
UseShellExecute = false,
|
| 301 |
+
RedirectStandardInput = true,
|
| 302 |
+
CreateNoWindow = true
|
| 303 |
+
};
|
| 304 |
+
|
| 305 |
+
Process ffmpegProcess = null;
|
| 306 |
+
try
|
| 307 |
+
{
|
| 308 |
+
ffmpegProcess = Process.Start(psi);
|
| 309 |
+
}
|
| 310 |
+
catch(Exception e)
|
| 311 |
+
{
|
| 312 |
+
UnityEngine.Debug.LogError($"Failed to start FFmpeg. Is it in PATH? Error: {e.Message}");
|
| 313 |
+
yield break;
|
| 314 |
+
}
|
| 315 |
+
|
| 316 |
+
Texture2D screenTex = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
|
| 317 |
+
RenderTexture depthRT = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.RFloat);
|
| 318 |
+
Texture2D depthReadTex = new Texture2D(Screen.width, Screen.height, TextureFormat.RFloat, false);
|
| 319 |
+
|
| 320 |
+
string jsonlPath = Path.Combine(outputFolder, $"sequence_{sequenceName}.jsonl");
|
| 321 |
+
|
| 322 |
+
int framesUntilSwitch = 0;
|
| 323 |
+
int currentFaceId = 0, currentLeftHandId = 0, currentRightHandId = 0;
|
| 324 |
+
|
| 325 |
+
using (var sw = new StreamWriter(jsonlPath, false))
|
| 326 |
+
{
|
| 327 |
+
for (int i = 0; i < _data.frames.Count; i++)
|
| 328 |
+
{
|
| 329 |
+
if (framesUntilSwitch <= 0)
|
| 330 |
+
{
|
| 331 |
+
framesUntilSwitch = UnityEngine.Random.Range(minSwitchFrames, maxSwitchFrames + 1);
|
| 332 |
+
currentFaceId = UnityEngine.Random.Range(0, faceMaxId + 1);
|
| 333 |
+
currentLeftHandId = UnityEngine.Random.Range(0, handsMaxId + 1);
|
| 334 |
+
currentRightHandId = UnityEngine.Random.Range(0, handsMaxId + 1);
|
| 335 |
+
if (_activeAnimator != null)
|
| 336 |
+
{
|
| 337 |
+
_activeAnimator.SetInteger(paramFaceIndex, currentFaceId);
|
| 338 |
+
_activeAnimator.SetInteger(paramLeftHandIndex, currentLeftHandId);
|
| 339 |
+
_activeAnimator.SetInteger(paramRightHandIndex, currentRightHandId);
|
| 340 |
+
}
|
| 341 |
+
}
|
| 342 |
+
framesUntilSwitch--;
|
| 343 |
+
|
| 344 |
+
ApplyFrame(_data.frames[i]);
|
| 345 |
+
if (cameraDriver != null) cameraDriver.OnFrame(i);
|
| 346 |
+
if (_activeRetargeter != null) _activeRetargeter.ManualUpdatePose();
|
| 347 |
+
|
| 348 |
+
Physics.SyncTransforms();
|
| 349 |
+
|
| 350 |
+
vtuberCamera.clearFlags = CameraClearFlags.SolidColor;
|
| 351 |
+
vtuberCamera.backgroundColor = Color.black;
|
| 352 |
+
vtuberCamera.cullingMask = ~0;
|
| 353 |
+
|
| 354 |
+
yield return new WaitForEndOfFrame();
|
| 355 |
+
|
| 356 |
+
if (screenTex.width != Screen.width || screenTex.height != Screen.height)
|
| 357 |
+
screenTex.Reinitialize(Screen.width, Screen.height);
|
| 358 |
+
|
| 359 |
+
screenTex.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
|
| 360 |
+
screenTex.Apply();
|
| 361 |
+
|
| 362 |
+
byte[] rawFrame = screenTex.GetRawTextureData();
|
| 363 |
+
if (ffmpegProcess != null && !ffmpegProcess.HasExited)
|
| 364 |
+
{
|
| 365 |
+
try {
|
| 366 |
+
ffmpegProcess.StandardInput.BaseStream.Write(rawFrame, 0, rawFrame.Length);
|
| 367 |
+
ffmpegProcess.StandardInput.BaseStream.Flush();
|
| 368 |
+
} catch (Exception ex) {
|
| 369 |
+
UnityEngine.Debug.LogError("FFmpeg write error: " + ex.Message);
|
| 370 |
+
}
|
| 371 |
+
}
|
| 372 |
+
|
| 373 |
+
RenderTexture origRT = vtuberCamera.targetTexture;
|
| 374 |
+
CameraClearFlags origFlags = vtuberCamera.clearFlags;
|
| 375 |
+
Color origBG = vtuberCamera.backgroundColor;
|
| 376 |
+
|
| 377 |
+
vtuberCamera.targetTexture = depthRT;
|
| 378 |
+
vtuberCamera.clearFlags = CameraClearFlags.SolidColor;
|
| 379 |
+
vtuberCamera.backgroundColor = new Color(1000f, 0, 0, 0);
|
| 380 |
+
|
| 381 |
+
if (_autoDepthShader != null) vtuberCamera.RenderWithShader(_autoDepthShader, "");
|
| 382 |
+
else vtuberCamera.Render();
|
| 383 |
+
|
| 384 |
+
RenderTexture.active = depthRT;
|
| 385 |
+
if (depthReadTex.width != Screen.width || depthReadTex.height != Screen.height)
|
| 386 |
+
depthReadTex.Reinitialize(Screen.width, Screen.height);
|
| 387 |
+
depthReadTex.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
|
| 388 |
+
depthReadTex.Apply();
|
| 389 |
+
|
| 390 |
+
if (saveDebugDepthImages)
|
| 391 |
+
{
|
| 392 |
+
Texture2D visualDepth = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
|
| 393 |
+
Color[] rawPixels = depthReadTex.GetPixels();
|
| 394 |
+
Color[] visPixels = new Color[rawPixels.Length];
|
| 395 |
+
float displayRange = 3.0f;
|
| 396 |
+
for (int k = 0; k < rawPixels.Length; k++)
|
| 397 |
+
{
|
| 398 |
+
float d = rawPixels[k].r;
|
| 399 |
+
if (d > 999f) visPixels[k] = Color.white;
|
| 400 |
+
else
|
| 401 |
+
{
|
| 402 |
+
float norm = Mathf.Clamp01(d / displayRange);
|
| 403 |
+
visPixels[k] = new Color(norm, norm, norm);
|
| 404 |
+
}
|
| 405 |
+
}
|
| 406 |
+
visualDepth.SetPixels(visPixels);
|
| 407 |
+
visualDepth.Apply();
|
| 408 |
+
string depthFile = $"depth_{i:D5}.png";
|
| 409 |
+
File.WriteAllBytes(Path.Combine(seqImageDir, depthFile), visualDepth.EncodeToPNG());
|
| 410 |
+
Destroy(visualDepth);
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
vtuberCamera.targetTexture = origRT;
|
| 414 |
+
vtuberCamera.clearFlags = origFlags;
|
| 415 |
+
vtuberCamera.backgroundColor = origBG;
|
| 416 |
+
RenderTexture.active = null;
|
| 417 |
+
|
| 418 |
+
ComputeBoundingBoxCached();
|
| 419 |
+
|
| 420 |
+
float H = Screen.height; float W = Screen.width;
|
| 421 |
+
// Compute intrinsics in CV convention (Y-down, origin top-left)
|
| 422 |
+
// Use Y-up point to get Unity-convention focal length, then negate for CV
|
| 423 |
+
Vector3 camP0_W = vtuberCamera.transform.TransformPoint(new Vector3(0f, 0f, 1f));
|
| 424 |
+
Vector3 camPx_W = vtuberCamera.transform.TransformPoint(new Vector3(1f, 0f, 1f));
|
| 425 |
+
Vector3 camPy_W = vtuberCamera.transform.TransformPoint(new Vector3(0f, 1f, 1f)); // Y-up in Unity
|
| 426 |
+
Vector3 s0 = vtuberCamera.WorldToScreenPoint(camP0_W);
|
| 427 |
+
Vector3 sx = vtuberCamera.WorldToScreenPoint(camPx_W);
|
| 428 |
+
Vector3 sy = vtuberCamera.WorldToScreenPoint(camPy_W);
|
| 429 |
+
float cx = s0.x;
|
| 430 |
+
float cy = H - s0.y; // Convert to CV (origin at top-left)
|
| 431 |
+
float fx = sx.x - s0.x;
|
| 432 |
+
float fy = (H - s0.y) - (H - sy.y); // In CV, fy should be positive when Y-up maps to screen-down
|
| 433 |
+
|
| 434 |
+
Rect rFull = _cachedHasBbox ? _cachedBbox : new Rect(0, 0, 0, 0);
|
| 435 |
+
float bbox_x = rFull.x; float bbox_y = H - (rFull.y + rFull.height);
|
| 436 |
+
float bbox_w = rFull.width; float bbox_h = rFull.height;
|
| 437 |
+
float clip_x0 = Mathf.Clamp(bbox_x, 0, W);
|
| 438 |
+
float clip_y0 = Mathf.Clamp(bbox_y, 0, H);
|
| 439 |
+
float clip_w = Mathf.Max(0, Mathf.Clamp(bbox_x + bbox_w, 0, W) - clip_x0);
|
| 440 |
+
float clip_h = Mathf.Max(0, Mathf.Clamp(bbox_y + bbox_h, 0, H) - clip_y0);
|
| 441 |
+
|
| 442 |
+
var kpts2D = new List<float>();
|
| 443 |
+
var kptsVis = new List<int>();
|
| 444 |
+
var kpts3D = new List<float>();
|
| 445 |
+
|
| 446 |
+
if (_activeMarkers != null)
|
| 447 |
+
{
|
| 448 |
+
for (int mi = 0; mi < _activeMarkers.Count; mi++)
|
| 449 |
+
{
|
| 450 |
+
Transform t = _activeMarkers[mi];
|
| 451 |
+
if (t == null) { continue; }
|
| 452 |
+
|
| 453 |
+
Vector3 wPos = t.position;
|
| 454 |
+
kpts3D.Add(wPos.x); kpts3D.Add(wPos.y); kpts3D.Add(wPos.z);
|
| 455 |
+
|
| 456 |
+
Vector3 sPos = vtuberCamera.WorldToScreenPoint(wPos);
|
| 457 |
+
float x_px = sPos.x;
|
| 458 |
+
float y_px = H - sPos.y;
|
| 459 |
+
kpts2D.Add(x_px); kpts2D.Add(y_px);
|
| 460 |
+
|
| 461 |
+
int vis = 0;
|
| 462 |
+
if (sPos.z > 0 && x_px >= 0 && x_px < W && sPos.y >= 0 && sPos.y < H)
|
| 463 |
+
{
|
| 464 |
+
int checkRadius = 2;
|
| 465 |
+
float requiredVisibilityRatio = 0.5f;
|
| 466 |
+
int totalSamples = 0;
|
| 467 |
+
int visibleSamples = 0;
|
| 468 |
+
float markerDistance = sPos.z;
|
| 469 |
+
|
| 470 |
+
for (int ox = -checkRadius; ox <= checkRadius; ox++)
|
| 471 |
+
{
|
| 472 |
+
for (int oy = -checkRadius; oy <= checkRadius; oy++)
|
| 473 |
+
{
|
| 474 |
+
int px = (int)sPos.x + ox;
|
| 475 |
+
int py = (int)sPos.y + oy;
|
| 476 |
+
if (px >= 0 && px < W && py >= 0 && py < H)
|
| 477 |
+
{
|
| 478 |
+
totalSamples++;
|
| 479 |
+
float pixelDepth = depthReadTex.GetPixel(px, py).r;
|
| 480 |
+
if (pixelDepth >= (markerDistance - occlusionBias))
|
| 481 |
+
visibleSamples++;
|
| 482 |
+
}
|
| 483 |
+
}
|
| 484 |
+
}
|
| 485 |
+
if (totalSamples > 0)
|
| 486 |
+
{
|
| 487 |
+
float visibilityPct = (float)visibleSamples / totalSamples;
|
| 488 |
+
vis = (visibilityPct >= requiredVisibilityRatio) ? 2 : 1;
|
| 489 |
+
}
|
| 490 |
+
else vis = 1;
|
| 491 |
+
}
|
| 492 |
+
kptsVis.Add(vis);
|
| 493 |
+
}
|
| 494 |
+
}
|
| 495 |
+
|
| 496 |
+
_cachedMarkerVis = kptsVis.ToArray();
|
| 497 |
+
Transform pelvis = (_bones != null && _bones.Length > 0) ? _bones[0] : null;
|
| 498 |
+
Vector3 pelvisPos = (pelvis != null) ? pelvis.position : Vector3.zero;
|
| 499 |
+
Quaternion pelvisWorld = (pelvis != null) ? pelvis.rotation : Quaternion.identity;
|
| 500 |
+
|
| 501 |
+
// --- SIMPLIFIED EXPORT: Raw Unity transforms only ---
|
| 502 |
+
// Python will derive incam and global consistently from these raw values
|
| 503 |
+
// using the approach in process_dataset_fromincam.py
|
| 504 |
+
|
| 505 |
+
// INCAM TRANSLATION: Camera-relative position (Y-flipped for CV)
|
| 506 |
+
Vector3 incamPos_unity = vtuberCamera.transform.InverseTransformPoint(pelvisPos);
|
| 507 |
+
Vector3 incamPos = new Vector3(incamPos_unity.x, -incamPos_unity.y, incamPos_unity.z);
|
| 508 |
+
Vector3 rootIncamPos_unity = (characterRoot != null) ? vtuberCamera.transform.InverseTransformPoint(characterRoot.transform.position) : Vector3.zero;
|
| 509 |
+
Vector3 rootIncamPos = new Vector3(rootIncamPos_unity.x, -rootIncamPos_unity.y, rootIncamPos_unity.z);
|
| 510 |
+
|
| 511 |
+
var meta = new OutputMeta
|
| 512 |
+
{
|
| 513 |
+
frame_index = i,
|
| 514 |
+
image_path = videoPath,
|
| 515 |
+
avatar_name = _activeAvatarName,
|
| 516 |
+
face_id = currentFaceId,
|
| 517 |
+
left_hand_id = currentLeftHandId,
|
| 518 |
+
right_hand_id = currentRightHandId,
|
| 519 |
+
bbox = new float[] { bbox_x, bbox_y, bbox_w, bbox_h },
|
| 520 |
+
bbox_clip = new float[] { clip_x0, clip_y0, clip_w, clip_h },
|
| 521 |
+
kpts_2d = kpts2D.ToArray(), kpts_vis = kptsVis.ToArray(),
|
| 522 |
+
cam_intrinsics = new float[] { fx, fy, cx, cy },
|
| 523 |
+
// RAW UNITY TRANSFORMS - Python derives everything from these
|
| 524 |
+
cam_pos_world = new float[] { vtuberCamera.transform.position.x, vtuberCamera.transform.position.y, vtuberCamera.transform.position.z },
|
| 525 |
+
cam_rot_world = new float[] { vtuberCamera.transform.rotation.x, vtuberCamera.transform.rotation.y, vtuberCamera.transform.rotation.z, vtuberCamera.transform.rotation.w },
|
| 526 |
+
pelvis_pos_world = new float[] { pelvisPos.x, pelvisPos.y, pelvisPos.z },
|
| 527 |
+
pelvis_rot_world = new float[] { pelvisWorld.x, pelvisWorld.y, pelvisWorld.z, pelvisWorld.w },
|
| 528 |
+
// INCAM TRANSLATION (only translation needs pre-conversion for CV Y-flip)
|
| 529 |
+
smpl_incam_transl = new float[] { incamPos.x, incamPos.y, incamPos.z },
|
| 530 |
+
smpl_root_incam_transl = new float[] { rootIncamPos.x, rootIncamPos.y, rootIncamPos.z },
|
| 531 |
+
smpl_root_world_scale = (characterRoot != null) ? characterRoot.transform.lossyScale.x : 1f,
|
| 532 |
+
kpts_3d_world = kpts3D.ToArray(),
|
| 533 |
+
smplx_pose = _data.frames[i].p, smplx_betas = _data.frames[i].b
|
| 534 |
+
// REMOVED: smpl_incam_quat, smpl_global_orient_unity, smpl_global_transl_unity
|
| 535 |
+
// Python derives incam/global rotation from pelvis_rot_world + cam_rot_world
|
| 536 |
+
};
|
| 537 |
+
sw.WriteLine(JsonConvert.SerializeObject(meta));
|
| 538 |
+
}
|
| 539 |
+
}
|
| 540 |
+
|
| 541 |
+
if (ffmpegProcess != null && !ffmpegProcess.HasExited)
|
| 542 |
+
{
|
| 543 |
+
ffmpegProcess.StandardInput.Close();
|
| 544 |
+
ffmpegProcess.WaitForExit();
|
| 545 |
+
ffmpegProcess.Close();
|
| 546 |
+
}
|
| 547 |
+
|
| 548 |
+
if(screenTex) Destroy(screenTex);
|
| 549 |
+
if(depthRT) Destroy(depthRT);
|
| 550 |
+
if(depthReadTex) Destroy(depthReadTex);
|
| 551 |
+
}
|
| 552 |
+
|
| 553 |
+
void ApplyFrame(FrameData f)
|
| 554 |
+
{
|
| 555 |
+
if (f.p == null || characterRoot == null) return;
|
| 556 |
+
Quaternion correction = Quaternion.Euler(globalCoordinateCorrection);
|
| 557 |
+
characterRoot.transform.localPosition = (correction * (new Vector3(-f.t[0], f.t[1], f.t[2]) * movementScale)) + translationOffset;
|
| 558 |
+
int floatIdx = 0;
|
| 559 |
+
for (int i = 0; i < JOINT_COUNT; i++)
|
| 560 |
+
{
|
| 561 |
+
if (floatIdx + 2 >= f.p.Length) break;
|
| 562 |
+
float x = f.p[floatIdx++], y = f.p[floatIdx++], z = f.p[floatIdx++];
|
| 563 |
+
float angle = Mathf.Sqrt(x * x + y * y + z * z);
|
| 564 |
+
Quaternion q = Quaternion.identity;
|
| 565 |
+
if (angle > 1e-6f) { float c = Mathf.Cos(angle * 0.5f), s = Mathf.Sin(angle * 0.5f); q = new Quaternion(-(x / angle) * s, (y / angle) * s, (z / angle) * s, -c); }
|
| 566 |
+
if (_bones != null && i < _bones.Length && _bones[i] != null) _bones[i].localRotation = (i == 0) ? (correction * q) : q;
|
| 567 |
+
}
|
| 568 |
+
if (cameraDriver != null) cameraDriver.SetStyleFromFrameData(f.s);
|
| 569 |
+
}
|
| 570 |
+
|
| 571 |
+
private void FindAndCacheBones()
|
| 572 |
+
{
|
| 573 |
+
_bones = new Transform[BONE_NAMES.Length];
|
| 574 |
+
for (int i = 0; i < BONE_NAMES.Length; i++) _bones[i] = FindDeep(characterRoot.transform, BONE_NAMES[i]);
|
| 575 |
+
_pelvisBone = (_bones != null && _bones.Length > 0) ? _bones[0] : null;
|
| 576 |
+
}
|
| 577 |
+
|
| 578 |
+
private static Transform FindDeep(Transform root, string name)
|
| 579 |
+
{
|
| 580 |
+
if (root.name == name) return root;
|
| 581 |
+
foreach (Transform child in root) { var res = FindDeep(child, name); if (res) return res; }
|
| 582 |
+
return null;
|
| 583 |
+
}
|
| 584 |
+
|
| 585 |
+
private void RandomizeAvatarAndGatherRenderers()
|
| 586 |
+
{
|
| 587 |
+
if (avatarList == null || avatarList.Count == 0) return;
|
| 588 |
+
_activeBboxRenderers.Clear(); _activeMarkers.Clear();
|
| 589 |
+
int randomIndex = UnityEngine.Random.Range(0, avatarList.Count);
|
| 590 |
+
AvatarConfig selected = avatarList[randomIndex];
|
| 591 |
+
_activeAvatarName = selected.avatarName;
|
| 592 |
+
_activeAnimator = selected.animator;
|
| 593 |
+
if (_activeAnimator == null && selected.avatarObject != null) _activeAnimator = selected.avatarObject.GetComponent<Animator>();
|
| 594 |
+
for (int i = 0; i < avatarList.Count; i++) if (avatarList[i].avatarObject != null) avatarList[i].avatarObject.SetActive(i == randomIndex);
|
| 595 |
+
_activePadding = selected.specificPadding; _activeRetargeter = selected.retargeter;
|
| 596 |
+
if (selected.avatarObject != null) _activeAvatarRoot = selected.avatarObject.transform;
|
| 597 |
+
if (selected.customMarkers != null) _activeMarkers.AddRange(selected.customMarkers);
|
| 598 |
+
if (characterRoot != null) { foreach (var r in characterRoot.GetComponentsInChildren<Renderer>(true)) _activeBboxRenderers.Add(r); }
|
| 599 |
+
foreach (GameObject extra in selected.extraMeshes) if (extra) { foreach (var cr in extra.GetComponentsInChildren<Renderer>(true)) if (!_activeBboxRenderers.Contains(cr)) _activeBboxRenderers.Add(cr); }
|
| 600 |
+
}
|
| 601 |
+
|
| 602 |
+
private void ApplyRandomSpawnPoint(Scene worldScene)
|
| 603 |
+
{
|
| 604 |
+
if (!worldScene.IsValid() || !worldScene.isLoaded) return;
|
| 605 |
+
List<Transform> spawns = new List<Transform>();
|
| 606 |
+
foreach (GameObject root in worldScene.GetRootGameObjects()) { foreach (Transform child in root.GetComponentsInChildren<Transform>(true)) if (child.name.Contains(spawnPointToken)) spawns.Add(child); }
|
| 607 |
+
if (spawns.Count > 0)
|
| 608 |
+
{
|
| 609 |
+
Transform chosen = spawns[UnityEngine.Random.Range(0, spawns.Count)];
|
| 610 |
+
this.transform.position = chosen.position; this.transform.rotation = chosen.rotation;
|
| 611 |
+
if (characterRoot != null) { characterRoot.transform.localPosition = Vector3.zero; characterRoot.transform.localRotation = Quaternion.identity; }
|
| 612 |
+
}
|
| 613 |
+
}
|
| 614 |
+
|
| 615 |
+
private void BindToWorldMainCameraOrLog(Scene worldScene)
|
| 616 |
+
{
|
| 617 |
+
Camera found = null;
|
| 618 |
+
foreach (GameObject root in worldScene.GetRootGameObjects())
|
| 619 |
+
{
|
| 620 |
+
foreach (Transform t in root.GetComponentsInChildren<Transform>(true))
|
| 621 |
+
if (t.name == worldMainCameraName && t.GetComponent<Camera>()) { found = t.GetComponent<Camera>(); break; }
|
| 622 |
+
if (found) break;
|
| 623 |
+
}
|
| 624 |
+
if (!found) return;
|
| 625 |
+
Vector3 ls = found.transform.lossyScale;
|
| 626 |
+
if (Mathf.Abs(ls.x - 1f) > 1e-4f || Mathf.Abs(ls.y - 1f) > 1e-4f || Mathf.Abs(ls.z - 1f) > 1e-4f)
|
| 627 |
+
{
|
| 628 |
+
found.transform.SetParent(null, true);
|
| 629 |
+
found.transform.localScale = Vector3.one;
|
| 630 |
+
}
|
| 631 |
+
if (vtuberCamera && vtuberCamera != found) vtuberCamera.enabled = false;
|
| 632 |
+
vtuberCamera = found;
|
| 633 |
+
cameraDriver = found.GetComponent<SyntheticCameraDriver>() ?? found.gameObject.AddComponent<SyntheticCameraDriver>();
|
| 634 |
+
cameraDriver.BindAndInit(found, characterRoot.transform);
|
| 635 |
+
}
|
| 636 |
+
|
| 637 |
+
private bool ComputeBoundingBoxCached()
|
| 638 |
+
{
|
| 639 |
+
_cachedHasBbox = false; _cachedBbox = new Rect(0, 0, 0, 0);
|
| 640 |
+
if (vtuberCamera == null || _activeBboxRenderers.Count == 0) return false;
|
| 641 |
+
float minVX = float.MaxValue, maxVX = float.MinValue, minVY = float.MaxValue, maxVY = float.MinValue;
|
| 642 |
+
bool foundAny = false;
|
| 643 |
+
int stride = Mathf.Max(1, bakedVertexStride);
|
| 644 |
+
foreach (var rend in _activeBboxRenderers)
|
| 645 |
+
{
|
| 646 |
+
if (!rend) continue;
|
| 647 |
+
if (useBakedSkinnedMeshForBbox && rend is SkinnedMeshRenderer smr)
|
| 648 |
+
{
|
| 649 |
+
_bakeMesh.Clear(); smr.BakeMesh(_bakeMesh); _bakedVerts.Clear(); _bakeMesh.GetVertices(_bakedVerts);
|
| 650 |
+
Matrix4x4 localToWorldNoScale = Matrix4x4.TRS(smr.transform.position, smr.transform.rotation, Vector3.one);
|
| 651 |
+
for (int vi = 0; vi < _bakedVerts.Count; vi += stride)
|
| 652 |
+
{
|
| 653 |
+
Vector3 vp = vtuberCamera.WorldToViewportPoint(localToWorldNoScale.MultiplyPoint3x4(_bakedVerts[vi]));
|
| 654 |
+
if (vp.z <= 0f) continue;
|
| 655 |
+
foundAny = true; minVX = Math.Min(minVX, vp.x); maxVX = Math.Max(maxVX, vp.x); minVY = Math.Min(minVY, vp.y); maxVY = Math.Max(maxVY, vp.y);
|
| 656 |
+
}
|
| 657 |
+
}
|
| 658 |
+
else
|
| 659 |
+
{
|
| 660 |
+
Bounds b = rend.bounds; Vector3 c = b.center, e = b.extents;
|
| 661 |
+
Vector3[] corners = { c+new Vector3(-e.x,-e.y,-e.z), c+new Vector3(-e.x,-e.y,e.z), c+new Vector3(-e.x,e.y,-e.z), c+new Vector3(-e.x,e.y,e.z), c+new Vector3(e.x,-e.y,-e.z), c+new Vector3(e.x,-e.y,e.z), c+new Vector3(e.x,e.y,-e.z), c+new Vector3(e.x,e.y,e.z) };
|
| 662 |
+
foreach (var corner in corners)
|
| 663 |
+
{
|
| 664 |
+
Vector3 vp = vtuberCamera.WorldToViewportPoint(corner);
|
| 665 |
+
if (vp.z <= 0f) continue;
|
| 666 |
+
foundAny = true; minVX = Math.Min(minVX, vp.x); maxVX = Math.Max(maxVX, vp.x); minVY = Math.Min(minVY, vp.y); maxVY = Math.Max(maxVY, vp.y);
|
| 667 |
+
}
|
| 668 |
+
}
|
| 669 |
+
}
|
| 670 |
+
if (!foundAny) return false;
|
| 671 |
+
_cachedBbox = new Rect(minVX * Screen.width - _activePadding, minVY * Screen.height - _activePadding, (maxVX - minVX) * Screen.width + _activePadding * 2, (maxVY - minVY) * Screen.height + _activePadding * 2);
|
| 672 |
+
_cachedHasBbox = true; return true;
|
| 673 |
+
}
|
| 674 |
+
|
| 675 |
+
void OnGUI()
|
| 676 |
+
{
|
| 677 |
+
if (!showDebugUI || vtuberCamera == null) return;
|
| 678 |
+
if (_cachedHasBbox) { Rect r = _cachedBbox; float invY = Screen.height - (r.y + r.height); GUI.DrawTexture(new Rect(r.x, invY, r.width, 3), _greenTex); GUI.DrawTexture(new Rect(r.x, invY + r.height, r.width, 3), _greenTex); GUI.DrawTexture(new Rect(r.x, invY, 3, r.height), _greenTex); GUI.DrawTexture(new Rect(r.x + r.width, invY, 3, r.height), _greenTex); }
|
| 679 |
+
if (_activeMarkers != null) { for (int mi = 0; mi < _activeMarkers.Count; mi++) { if (!_activeMarkers[mi]) continue; Vector3 sc = vtuberCamera.WorldToScreenPoint(_activeMarkers[mi].position); if (sc.z > 0) { int vis = (_cachedMarkerVis != null && mi < _cachedMarkerVis.Length) ? _cachedMarkerVis[mi] : 2; GUI.DrawTexture(new Rect(sc.x - 2, Screen.height - sc.y - 2, 4, 4), vis == 1 ? _occTex : _greenTex); } } }
|
| 680 |
+
}
|
| 681 |
+
}
|
TODO.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Hands (plug-and-play 3D, no fitting): HaMeR
|
| 2 |
+
|
| 3 |
+
Use HaMeR (Hand Mesh Recovery).
|
| 4 |
+
|
| 5 |
+
Input: hand bounding box + hand side (L/R) + image
|
| 6 |
+
|
| 7 |
+
https://geopavlakos.github.io/hamer/?utm_source=chatgpt.com
|
| 8 |
+
|
| 9 |
+
Hand4Whole exists, but it’s a full pipeline; HaMeR is the cleanest “hands-only module.”
|
| 10 |
+
|
| 11 |
+
Face to Emotion state for labeling facial expressions.
|
| 12 |
+
|
| 13 |
+
ViT Facial Expression Recognition
|
| 14 |
+
HuggingFace (same model, easier)
|
| 15 |
+
|
| 16 |
+
👉 https://huggingface.co/nateraw/vit-base-facial-expression-recognition
|
| 17 |
+
|
| 18 |
+
DeepFace (simple, classic, works)
|
| 19 |
+
👉 https://github.com/serengil/deepface
|
| 20 |
+
|
| 21 |
+
CLIP zero-shot emotion classification
|
_DATA/hamer_demo_data.tar.gz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:bb4573f1ed131923eb6fa2e9537766b367095b71afc536e46767b95e0debc37f
|
| 3 |
+
size 217497600
|
bedlam_GT.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:719aa90ff80e2339aa4e7a96ccf243ae0e78860c4735baec32c8ab452bd98d19
|
| 3 |
+
size 212875004
|
configs/__init__.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import os
|
| 3 |
+
|
| 4 |
+
from hydra import compose, initialize_config_module
|
| 5 |
+
from hydra.core.config_store import ConfigStore
|
| 6 |
+
|
| 7 |
+
os.environ["HYDRA_FULL_ERROR"] = "1"
|
| 8 |
+
|
| 9 |
+
MainStore = ConfigStore.instance()
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def parse_args_to_cfg():
|
| 13 |
+
"""
|
| 14 |
+
Use minimal Hydra API to parse args and return cfg.
|
| 15 |
+
This function don't do _run_hydra which create log file hierarchy.
|
| 16 |
+
"""
|
| 17 |
+
parser = argparse.ArgumentParser()
|
| 18 |
+
parser.add_argument("--config-name", "-cn", default="train")
|
| 19 |
+
parser.add_argument(
|
| 20 |
+
"overrides",
|
| 21 |
+
nargs="*",
|
| 22 |
+
help="Any key=value arguments to override config values (use dots for.nested=overrides)",
|
| 23 |
+
)
|
| 24 |
+
args = parser.parse_args()
|
| 25 |
+
|
| 26 |
+
# Cfg
|
| 27 |
+
with initialize_config_module(version_base="1.3", config_module="configs"):
|
| 28 |
+
cfg = compose(config_name=args.config_name, overrides=args.overrides)
|
| 29 |
+
|
| 30 |
+
return cfg
|
configs/callbacks/ckpt_saver/every10000s_top100.yaml
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
every10000s_top100:
|
| 2 |
+
_target_: genmo.callbacks.simple_ckpt_saver.SimpleCkptSaver
|
| 3 |
+
output_dir: ${output_dir}/checkpoints/
|
| 4 |
+
every_n_steps: 10000
|
| 5 |
+
save_top_k: 100
|
configs/callbacks/lr_monitor/pl.yaml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
pl:
|
| 2 |
+
_target_: pytorch_lightning.callbacks.lr_monitor.LearningRateMonitor
|
configs/callbacks/metric/metric_3dpw.yaml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
metric_3dpw:
|
| 2 |
+
_target_: genmo.callbacks.metric.metric_3dpw.MetricMocap
|
configs/callbacks/metric/metric_3dpw_occ.yaml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
metric_3dpw_occ:
|
| 2 |
+
_target_: genmo.callbacks.metric.metric_3dpw_occ.MetricMocap
|
configs/callbacks/metric/metric_aistpp.yaml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
metric_aistpp:
|
| 2 |
+
_target_: genmo.callbacks.metric.metric_aistpp.MetricMusic
|
configs/callbacks/metric/metric_emdb1.yaml
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
metric_emdb1:
|
| 2 |
+
_target_: genmo.callbacks.metric.metric_emdb.MetricMocap
|
| 3 |
+
emdb_split: 1
|
| 4 |
+
occ: false
|
configs/callbacks/metric/metric_emdb2.yaml
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
metric_emdb2:
|
| 2 |
+
_target_: genmo.callbacks.metric.metric_emdb.MetricMocap
|
| 3 |
+
emdb_split: 2
|
| 4 |
+
occ: false
|
configs/callbacks/metric/metric_rich.yaml
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
metric_rich:
|
| 2 |
+
_target_: genmo.callbacks.metric.metric_rich.MetricMocap
|
| 3 |
+
occ: false
|
configs/callbacks/metric/metric_unity.yaml
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
metric_unity:
|
| 2 |
+
_target_: genmo.callbacks.metric.metric_unity.MetricUnity
|
| 3 |
+
# Disable the old scenepic HTML viz by default (use `vis/vis_unity_val` instead).
|
| 4 |
+
vis_every_n_val: 1000000000
|
configs/callbacks/prog_bar/prog_reporter_ed1.yaml
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
prog_reporter_ed1:
|
| 2 |
+
_target_: genmo.callbacks.prog_bar.ProgressReporter
|
| 3 |
+
log_every_percent: 0.1
|
| 4 |
+
exp_name: ${exp_name}
|
| 5 |
+
data_name: ${data_name}
|
configs/callbacks/train_speed_timer/base.yaml
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
base:
|
| 2 |
+
_target_: genmo.callbacks.train_speed_timer.TrainSpeedTimer
|
| 3 |
+
N_avg: 5
|
configs/callbacks/vis/vis_music.yaml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
vis_music:
|
| 2 |
+
_target_: genmo.callbacks.vis.vis_music.VisMusic
|
configs/callbacks/vis/vis_speech.yaml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
vis_speech:
|
| 2 |
+
_target_: genmo.callbacks.vis.vis_speech.VisSpeech
|
configs/callbacks/vis/vis_text.yaml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
vis_text:
|
| 2 |
+
_target_: genmo.callbacks.vis.vis_text.VisText
|
configs/callbacks/vis/vis_unity_val.yaml
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
vis_unity_val:
|
| 2 |
+
_target_: genmo.callbacks.vis.vis_unity_val.VisUnityVal
|
| 3 |
+
enabled: false
|
| 4 |
+
every_n_epochs: 1
|
| 5 |
+
num_batches: 1
|
| 6 |
+
# Which val batches to render: "first" or "random".
|
| 7 |
+
batch_select: "first"
|
| 8 |
+
batch_select_seed: 123
|
| 9 |
+
num_frames: 30
|
| 10 |
+
render_incam: true
|
| 11 |
+
render_global: true
|
| 12 |
+
use_gt_betas_for_pred: true
|
| 13 |
+
global_root_relative: false
|
| 14 |
+
crf: 23
|
| 15 |
+
save_dir: ${output_dir}/vis
|
| 16 |
+
pred_color: [176, 100, 244]
|
| 17 |
+
gt_color: [0, 255, 0]
|
configs/data/collate_cfg/default.yaml
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
max_motion_frames: ${data.dataset_opts.max_motion_frames}
|
| 2 |
+
default_frame_feature_dim:
|
| 3 |
+
music_array: [1024]
|
| 4 |
+
music_embed: [35]
|
| 5 |
+
music_beats: []
|
| 6 |
+
audio_array: []
|
| 7 |
+
use_det_kp: []
|
| 8 |
+
|
| 9 |
+
default_seq_feature_dim:
|
| 10 |
+
text_embed: [50, 1024]
|
| 11 |
+
|
| 12 |
+
default_seq_feature_length_multiplier:
|
| 13 |
+
audio_array: 600
|
| 14 |
+
|
| 15 |
+
default_feature_val:
|
| 16 |
+
caption: ""
|
| 17 |
+
music_fps: 30
|
| 18 |
+
audio_fps: 30
|
| 19 |
+
has_text: False
|
| 20 |
+
# has_audio: False
|
| 21 |
+
# has_music: False
|
| 22 |
+
|
| 23 |
+
default_feature_type: {}
|
configs/data/mocap/trainX_testY.yaml
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
defaults:
|
| 2 |
+
- collate_cfg: default
|
| 3 |
+
|
| 4 |
+
# definition of lightning datamodule (dataset + dataloader)
|
| 5 |
+
_target_: genmo.datamodule.mocap_trainX_testY.DataModule
|
| 6 |
+
|
| 7 |
+
dataset_opts:
|
| 8 |
+
train: ${train_datasets}
|
| 9 |
+
val: ${test_datasets}
|
| 10 |
+
max_motion_frames: 120
|
| 11 |
+
|
| 12 |
+
loader_opts:
|
| 13 |
+
train:
|
| 14 |
+
batch_size: 128
|
| 15 |
+
num_workers: 8
|
| 16 |
+
val:
|
| 17 |
+
batch_size: 1
|
| 18 |
+
num_workers: 1
|
| 19 |
+
encoded_music_dim: ${pipeline.args.encoded_music_dim}
|
| 20 |
+
|
| 21 |
+
limit_each_trainset: null
|
configs/demo.yaml
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
defaults:
|
| 2 |
+
# pytorch-lightning
|
| 3 |
+
- data: ???
|
| 4 |
+
- model: ???
|
| 5 |
+
- /text_encoder@model.model_cfg.text_encoder: t5_3b
|
| 6 |
+
- callbacks: null
|
| 7 |
+
|
| 8 |
+
# system
|
| 9 |
+
- hydra: default
|
| 10 |
+
|
| 11 |
+
# utility groups that changes a lot
|
| 12 |
+
- pipeline: null
|
| 13 |
+
- network: null
|
| 14 |
+
- optimizer: null
|
| 15 |
+
- scheduler: null
|
| 16 |
+
- train_datasets: null
|
| 17 |
+
- test_datasets: null
|
| 18 |
+
- endecoder: null # normalize/unnormalize data
|
| 19 |
+
- refiner: null
|
| 20 |
+
|
| 21 |
+
# global-override
|
| 22 |
+
- exp: mixed # set "data, model and callbacks" in yaml
|
| 23 |
+
- global/task: null # dump/test
|
| 24 |
+
- global/hsearch: null # hyper-param search
|
| 25 |
+
- global/debug: null # debug mode
|
| 26 |
+
- _self_
|
| 27 |
+
|
| 28 |
+
# ================================ #
|
| 29 |
+
# global setting #
|
| 30 |
+
# ================================ #
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
# expirement information
|
| 34 |
+
task: fit # [fit, predict]
|
| 35 |
+
exp_name_base: ???
|
| 36 |
+
exp_name_var: ""
|
| 37 |
+
exp_name: ${exp_name_base}_${exp_name_var}
|
| 38 |
+
data_name: ???
|
| 39 |
+
|
| 40 |
+
# utilities in the entry file
|
| 41 |
+
# output_dir: "outputs/${data_name}/${exp_name}"
|
| 42 |
+
resume_mode: null
|
| 43 |
+
seed: 42
|
| 44 |
+
|
| 45 |
+
version: null
|
| 46 |
+
ckpt_dir: outputs/${data_name}/${exp_name}/
|
| 47 |
+
remote_results_path: /lustre/fsw/portfolios/nvr/projects/nvr_torontoai_humanmotionfm/workspaces/motiondiff/motiondiff_results/jiefengl/gvhmr
|
| 48 |
+
ckpt_path: null
|
| 49 |
+
|
| 50 |
+
###
|
| 51 |
+
# W&B logging removed from this repo; TensorBoard is used by `scripts/train.py`.
|
| 52 |
+
rsync_ckpt: true
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
# ================================ #
|
| 56 |
+
# global setting #
|
| 57 |
+
# ================================ #
|
| 58 |
+
|
| 59 |
+
video_name: ???
|
| 60 |
+
output_root: outputs/demo
|
| 61 |
+
output_dir: "${output_root}/${text1_video_name}"
|
| 62 |
+
preprocess_dir: ${output_dir}/preprocess
|
| 63 |
+
video_path: "${output_dir}/0_input_video.mp4"
|
| 64 |
+
|
| 65 |
+
# Options
|
| 66 |
+
text1: null
|
| 67 |
+
text1_file: null
|
| 68 |
+
text1_video_path: null
|
| 69 |
+
text1_video_name: null
|
| 70 |
+
text_length: 300
|
| 71 |
+
static_cam: False
|
| 72 |
+
verbose: False
|
| 73 |
+
|
| 74 |
+
paths:
|
| 75 |
+
bbx: ${preprocess_dir}/bbx.pt
|
| 76 |
+
bbx_xyxy_video_overlay: ${preprocess_dir}/bbx_xyxy_video_overlay.mp4
|
| 77 |
+
vit_features: ${preprocess_dir}/vit_features.pt
|
| 78 |
+
vimo_pred: ${preprocess_dir}/vimo_pred.pt
|
| 79 |
+
vitpose: ${preprocess_dir}/vitpose.pt
|
| 80 |
+
vitpose_video_overlay: ${preprocess_dir}/vitpose_video_overlay.mp4
|
| 81 |
+
hmr4d_results: ${output_dir}/hmr4d_results.pt
|
| 82 |
+
incam_video: ${output_dir}/1_incam.mp4
|
| 83 |
+
global_video: ${output_dir}/2_global.mp4
|
| 84 |
+
incam_global_horiz_video: ${output_dir}/3_incam_global_horiz.mp4
|
| 85 |
+
slam: ${preprocess_dir}/camera.npy
|
configs/diffusion/ddim.yaml
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
sampler: ddim
|
| 2 |
+
train_timestep_respacing: ""
|
| 3 |
+
test_timestep_respacing: "50"
|
| 4 |
+
schedule_sampler_type: uniform
|
| 5 |
+
noise_schedule: cosine
|
| 6 |
+
sigma_small: true
|
| 7 |
+
guidance_param: 1.0
|
| 8 |
+
ddim_eta: 0.0
|
configs/endecoder/unity.yaml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: genmo.network.endecoder.EnDecoder
|
| 2 |
+
stats_name: MM_UNITY
|
configs/endecoder/v1_amass_local_bedlam_cam.yaml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: genmo.network.endecoder.EnDecoder
|
| 2 |
+
stats_name: MM_V1_AMASS_LOCAL_BEDLAM_CAM
|
configs/exp/genmo_lg.yaml
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# @package _global_
|
| 2 |
+
defaults:
|
| 3 |
+
- /diffusion@model_cfg.diffusion: ddim
|
| 4 |
+
- override /data: mocap/trainX_testY
|
| 5 |
+
- override /model: genmo
|
| 6 |
+
- override /network: diffusion
|
| 7 |
+
- override /pipeline: dual_mode
|
| 8 |
+
- override /endecoder: v1_amass_local_bedlam_cam
|
| 9 |
+
- override /optimizer: adamw_2e-4
|
| 10 |
+
- override /scheduler: epoch_half_200_350
|
| 11 |
+
- override /train_datasets:
|
| 12 |
+
- amass_train_v11
|
| 13 |
+
- humanml3d_static_train
|
| 14 |
+
- bedlam_v2
|
| 15 |
+
- h36m_v1
|
| 16 |
+
- 3dpw_v1
|
| 17 |
+
- 3dpw_occ_v1
|
| 18 |
+
- aistpp_train
|
| 19 |
+
- beat2_static_train
|
| 20 |
+
- override /test_datasets:
|
| 21 |
+
# - aistpp_test
|
| 22 |
+
- humanml3d_eval
|
| 23 |
+
- emdb1_fliptest
|
| 24 |
+
- emdb2_fliptest
|
| 25 |
+
- rich_test
|
| 26 |
+
- 3dpw_fliptest
|
| 27 |
+
- 3dpw_occ_fliptest
|
| 28 |
+
- override /callbacks:
|
| 29 |
+
- ckpt_saver/every10000s_top100
|
| 30 |
+
- prog_bar/prog_reporter_ed1
|
| 31 |
+
- train_speed_timer/base
|
| 32 |
+
- lr_monitor/pl
|
| 33 |
+
- vis/vis_text
|
| 34 |
+
- metric/metric_emdb1
|
| 35 |
+
- metric/metric_emdb2
|
| 36 |
+
- metric/metric_rich
|
| 37 |
+
- metric/metric_3dpw
|
| 38 |
+
- metric/metric_3dpw_occ
|
| 39 |
+
# - metric_aistpp
|
| 40 |
+
- _self_
|
| 41 |
+
|
| 42 |
+
exp_name_base: ${hydra:runtime.choices.exp}
|
| 43 |
+
exp_name_var: ""
|
| 44 |
+
exp_name: ${exp_name_base}_${exp_name_var}
|
| 45 |
+
data_name: genmo_mixed
|
| 46 |
+
|
| 47 |
+
multicond_args: null
|
| 48 |
+
|
| 49 |
+
pl_trainer:
|
| 50 |
+
precision: 16-mixed
|
| 51 |
+
log_every_n_steps: 10
|
| 52 |
+
gradient_clip_val: 0.5
|
| 53 |
+
max_epochs: null
|
| 54 |
+
check_val_every_n_epoch: null
|
| 55 |
+
val_check_interval: 3000
|
| 56 |
+
max_steps: 200000
|
| 57 |
+
devices: 1
|
| 58 |
+
strategy: ddp_find_unused_parameters_true
|
| 59 |
+
|
| 60 |
+
logger:
|
| 61 |
+
_target_: pytorch_lightning.loggers.tensorboard.TensorBoardLogger
|
| 62 |
+
save_dir: ${output_dir}
|
| 63 |
+
name: ""
|
| 64 |
+
version: ""
|
configs/finetune_unity.yaml
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# genmo/configs/finetune_unity.yaml
|
| 2 |
+
defaults:
|
| 3 |
+
- train
|
| 4 |
+
- override /exp: genmo_lg
|
| 5 |
+
- override /optimizer: adamw_5e-5
|
| 6 |
+
- override /scheduler: cosine_50
|
| 7 |
+
# Keep only generic callbacks; drop dataset-specific metrics/visualizers.
|
| 8 |
+
- override /callbacks:
|
| 9 |
+
- ckpt_saver/every10000s_top100
|
| 10 |
+
- prog_bar/prog_reporter_ed1
|
| 11 |
+
- train_speed_timer/base
|
| 12 |
+
- lr_monitor/pl
|
| 13 |
+
- metric/metric_unity
|
| 14 |
+
- vis/vis_unity_val
|
| 15 |
+
- _self_
|
| 16 |
+
|
| 17 |
+
# Fix logging path mismatch by forcing filename to be local to the run dir
|
| 18 |
+
hydra:
|
| 19 |
+
job_logging:
|
| 20 |
+
handlers:
|
| 21 |
+
file:
|
| 22 |
+
filename: train.log
|
| 23 |
+
|
| 24 |
+
# Define mandatory variables and sync output_dir with Hydra run dir
|
| 25 |
+
data_name: "unity"
|
| 26 |
+
exp_name_base: "finetune"
|
| 27 |
+
# Keep `output_dir` from `configs/train.yaml` to avoid a Hydra/OmegaConf interpolation cycle:
|
| 28 |
+
# `hydra.run.dir` -> `${output_dir}` (configs/hydra/default.yaml) and `output_dir` -> `${hydra:run.dir}` would recurse.
|
| 29 |
+
|
| 30 |
+
# Save a checkpoint every N epochs.
|
| 31 |
+
callbacks:
|
| 32 |
+
ckpt_saver:
|
| 33 |
+
every10000s_top100:
|
| 34 |
+
every_n_steps: null
|
| 35 |
+
every_n_epochs: 100
|
| 36 |
+
save_top_k: 1
|
| 37 |
+
vis:
|
| 38 |
+
vis_unity_val:
|
| 39 |
+
enabled: true
|
| 40 |
+
batch_select: "random"
|
| 41 |
+
batch_select_seed: 123
|
| 42 |
+
pad_incam_canvas: false
|
| 43 |
+
incam_background: "video"
|
| 44 |
+
|
| 45 |
+
train_datasets:
|
| 46 |
+
unity:
|
| 47 |
+
_target_: genmo.datasets.unity_dataset.UnityDataset
|
| 48 |
+
root: "./processed_dataset"
|
| 49 |
+
# ORIGINAL dataset folder (same as `third_party/GVHMR/process_data.sh --input ...`) for mp4 backgrounds.
|
| 50 |
+
raw_root: "/mnt/c/Temp/SyntheticDataset"
|
| 51 |
+
split: "train"
|
| 52 |
+
motion_frames: 120 # Must be >= 91 for augmentation (L - 90 > 0)
|
| 53 |
+
# Keep the exact coordinate convention exported by `third_party/GVHMR/tools/demo/process_dataset.py`.
|
| 54 |
+
# Any extra basis swap here will desync `T_w2c`/cam velocities from the stored features/crops.
|
| 55 |
+
convert_world_to_az: false
|
| 56 |
+
# Use detector/VitPose kp2d as conditioning (inference-style).
|
| 57 |
+
vitpose_like: true
|
| 58 |
+
kp2d_clamp_to_image: false
|
| 59 |
+
kp2d_zero_oof: true
|
| 60 |
+
# Explicitly disable datasets inherited from `exp=genmo_lg`.
|
| 61 |
+
amass_train_v11: null
|
| 62 |
+
humanml3d_static_train: null
|
| 63 |
+
bedlam_v2: null
|
| 64 |
+
h36m_v1: null
|
| 65 |
+
3dpw_v1: null
|
| 66 |
+
3dpw_occ_v1: null
|
| 67 |
+
aistpp_train: null
|
| 68 |
+
beat2_static_train: null
|
| 69 |
+
|
| 70 |
+
test_datasets:
|
| 71 |
+
unity_val:
|
| 72 |
+
_target_: genmo.datasets.unity_dataset.UnityDataset
|
| 73 |
+
root: "./processed_dataset"
|
| 74 |
+
raw_root: "/mnt/c/Temp/SyntheticDataset"
|
| 75 |
+
split: "train"
|
| 76 |
+
motion_frames: 120 # Must match train setting
|
| 77 |
+
convert_world_to_az: false
|
| 78 |
+
vitpose_like: true
|
| 79 |
+
kp2d_clamp_to_image: false
|
| 80 |
+
kp2d_zero_oof: true
|
| 81 |
+
# Explicitly disable test datasets inherited from `exp=genmo_lg`.
|
| 82 |
+
humanml3d_eval: null
|
| 83 |
+
emdb1_fliptest: null
|
| 84 |
+
emdb2_fliptest: null
|
| 85 |
+
rich_test: null
|
| 86 |
+
3dpw_fliptest: null
|
| 87 |
+
3dpw_occ_fliptest: null
|
| 88 |
+
|
| 89 |
+
# Fine-tuning Hyperparameters
|
| 90 |
+
# Lightning Trainer settings
|
| 91 |
+
pl_trainer:
|
| 92 |
+
max_epochs: 50 # More epochs for full adaptation
|
| 93 |
+
check_val_every_n_epoch: 1
|
| 94 |
+
log_every_n_steps: 1
|
| 95 |
+
precision: 16-mixed # Must match checkpoint (was trained with fp16)
|
| 96 |
+
gradient_clip_val: 0.5 # Tighter clipping (was 1.0)
|
| 97 |
+
val_check_interval: 1.0
|
| 98 |
+
limit_val_batches: 1.0
|
| 99 |
+
accumulate_grad_batches: 4 # Effective batch size = 4 * batch_size
|
| 100 |
+
|
| 101 |
+
# Fine-tune stability overrides:
|
| 102 |
+
# - Regression-only prevents diffusion loss from destabilizing global trajectory on small datasets.
|
| 103 |
+
# - Disable heavy masking/occlusion augmentation used for large-scale pretraining.
|
| 104 |
+
model:
|
| 105 |
+
model_cfg:
|
| 106 |
+
train_modes: ["regression"]
|
| 107 |
+
mask_transl_vel_y: false
|
| 108 |
+
condition_mask:
|
| 109 |
+
mask_img_prob: 0.0
|
| 110 |
+
mask_cam_prob: 0.0
|
| 111 |
+
mask_cfg:
|
| 112 |
+
drop_prob: 0.0
|
| 113 |
+
body_mask_cfg:
|
| 114 |
+
drop_prob: 0.0
|
| 115 |
+
|
| 116 |
+
# Disable huge reprojection/vertex losses for Unity fine-tune; keep global rollout + static-conf.
|
| 117 |
+
pipeline:
|
| 118 |
+
args:
|
| 119 |
+
transl_w_xz_only: false
|
| 120 |
+
pp_ground: false
|
| 121 |
+
weights:
|
| 122 |
+
cr_j3d: 0.0
|
| 123 |
+
# Keep incam stable: supervise pred_cam (via gt transl_c -> gt_pred_cam).
|
| 124 |
+
transl_c: 1.0
|
| 125 |
+
cr_verts: 0.0
|
| 126 |
+
j2d: 0.0
|
| 127 |
+
j2d_17: 0.0
|
| 128 |
+
verts2d: 0.0
|
| 129 |
+
transl_w: 1.0
|
| 130 |
+
static_conf_bce: 1.0
|
| 131 |
+
gogv_mult: 1.0
|
| 132 |
+
transl_vel_mult: 1.0
|
| 133 |
+
|
| 134 |
+
# Override the default dktaloader settings from `exp=genmo_lg` (it uses batch_size=128
|
| 135 |
+
# and the DataModule uses `drop_last=True`, which yields 0 batches for small Unity sets).
|
| 136 |
+
data:
|
| 137 |
+
loader_opts:
|
| 138 |
+
train:
|
| 139 |
+
batch_size: 2
|
| 140 |
+
num_workers: 2
|
| 141 |
+
val:
|
| 142 |
+
batch_size: 2
|
| 143 |
+
num_workers: 2
|
configs/hydra/default.yaml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# enable color logging
|
| 2 |
+
defaults:
|
| 3 |
+
- override hydra_logging: colorlog
|
| 4 |
+
- override job_logging: colorlog
|
| 5 |
+
|
| 6 |
+
job_logging:
|
| 7 |
+
formatters:
|
| 8 |
+
simple:
|
| 9 |
+
datefmt: "%m/%d %H:%M:%S"
|
| 10 |
+
format: "[%(asctime)s][%(levelname)s] %(message)s"
|
| 11 |
+
colorlog:
|
| 12 |
+
datefmt: "%m/%d %H:%M:%S"
|
| 13 |
+
format: "[%(cyan)s%(asctime)s%(reset)s][%(log_color)s%(levelname)s%(reset)s] %(message)s"
|
| 14 |
+
handlers:
|
| 15 |
+
file:
|
| 16 |
+
filename: ${output_dir}/${hydra.job.name}.log
|
| 17 |
+
|
| 18 |
+
run:
|
| 19 |
+
dir: ${output_dir}
|
configs/infer_video.yaml
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
defaults:
|
| 2 |
+
# pytorch-lightning / hydra wiring (kept for compatibility with `exp=...` configs)
|
| 3 |
+
- data: ???
|
| 4 |
+
- model: ???
|
| 5 |
+
- callbacks: null
|
| 6 |
+
- hydra: default
|
| 7 |
+
- pipeline: null
|
| 8 |
+
- network: null
|
| 9 |
+
- optimizer: null
|
| 10 |
+
- scheduler: null
|
| 11 |
+
- train_datasets: null
|
| 12 |
+
- test_datasets: null
|
| 13 |
+
- endecoder: null
|
| 14 |
+
- refiner: null
|
| 15 |
+
|
| 16 |
+
# pick an experiment preset (sets data/model/network/pipeline/etc)
|
| 17 |
+
- exp: genmo_lg
|
| 18 |
+
- _self_
|
| 19 |
+
|
| 20 |
+
# Video -> SMPL-X inference (GENMO/GEM)
|
| 21 |
+
video_path: null
|
| 22 |
+
video_name: null
|
| 23 |
+
|
| 24 |
+
output_root: outputs/infer_video
|
| 25 |
+
output_dir: ${output_root}/${video_name}
|
| 26 |
+
preprocess_dir: ${output_dir}/preprocess
|
| 27 |
+
|
| 28 |
+
# Checkpoint
|
| 29 |
+
ckpt_path: null
|
| 30 |
+
|
| 31 |
+
# Inference options
|
| 32 |
+
static_cam: true
|
| 33 |
+
use_kp2d: true
|
| 34 |
+
postproc: true
|
| 35 |
+
use_sam_masking: true # Apply SAM masks to VitPose and ViT features (removes background/other people)
|
| 36 |
+
run_hamer: false # Run HaMeR for hand mesh recovery (adds hand poses to SMPL-X)
|
| 37 |
+
resample_to_30fps: true
|
| 38 |
+
verbose: false
|
| 39 |
+
|
| 40 |
+
# Rendering
|
| 41 |
+
render_incam: true
|
| 42 |
+
render_global: true
|
| 43 |
+
render_side_by_side: true
|
| 44 |
+
render_crf: 23
|
| 45 |
+
|
| 46 |
+
# Optional: face visibility + emotion classification from face crop.
|
| 47 |
+
# Uses COCO17 head keypoints to estimate a face bbox; classifier is loaded from HF cache by default (offline-friendly).
|
| 48 |
+
emotion:
|
| 49 |
+
enabled: true
|
| 50 |
+
model_id: clip:openai/clip-vit-base-patch32
|
| 51 |
+
cache_dir: ./third_party/GVHMR/.cache/huggingface
|
| 52 |
+
local_files_only: true
|
| 53 |
+
min_kpt_conf: 0.3
|
| 54 |
+
min_visible_kpts: 3
|
| 55 |
+
face_bbox_scale: 2.0
|
| 56 |
+
# Optional alternative output location; `${preprocess_dir}/emotion.jsonl` is always preferred for overlays.
|
| 57 |
+
output_path: null
|
| 58 |
+
|
| 59 |
+
# Debug dump: save inputs + model outputs for offline analysis.
|
| 60 |
+
dump_io: false
|
| 61 |
+
dump_io_path: ${output_dir}/debug_io.pt
|
| 62 |
+
|
| 63 |
+
# Optional visualization: draw estimated camera axes in the global render.
|
| 64 |
+
draw_camera_axes: false
|
| 65 |
+
# Camera pose convention for `paths.slam` (affects camera-axis visualization only):
|
| 66 |
+
# - auto: choose the one closest to the person root each frame
|
| 67 |
+
# - w2c: interpret trajectory as world->camera
|
| 68 |
+
# - c2w: interpret trajectory as camera->world
|
| 69 |
+
camera_pose_convention: auto
|
| 70 |
+
camera_axis_length: 0.5
|
| 71 |
+
camera_axis_width: 3
|
| 72 |
+
|
| 73 |
+
paths:
|
| 74 |
+
input_video: ${output_dir}/0_input_video.mp4
|
| 75 |
+
video_30fps: ${output_dir}/0_input_video_30fps.mp4
|
| 76 |
+
bbx: ${preprocess_dir}/bbx.pt
|
| 77 |
+
vitpose: ${preprocess_dir}/vitpose.pt
|
| 78 |
+
vit_features: ${preprocess_dir}/vit_features.pt
|
| 79 |
+
hmr4d_results: ${output_dir}/hmr4d_results.pt
|
| 80 |
+
incam_video: ${output_dir}/1_incam.mp4
|
| 81 |
+
global_video: ${output_dir}/2_global.mp4
|
| 82 |
+
incam_global_horiz_video: ${output_dir}/3_incam_global_horiz.mp4
|
| 83 |
+
# Disable external logging by default for a local demo script.
|
| 84 |
+
###
|
| 85 |
+
# W&B logging removed from this repo; TensorBoard is used by `scripts/train.py` for training runs.
|
configs/model/genmo.yaml
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: genmo.genmo.GENMO
|
| 2 |
+
|
| 3 |
+
pipeline: ${pipeline}
|
| 4 |
+
optimizer: ${optimizer}
|
| 5 |
+
scheduler: ${scheduler}
|
| 6 |
+
|
| 7 |
+
model_cfg:
|
| 8 |
+
train_modes: ["regression", "diffusion"]
|
| 9 |
+
noisy_2d_obs: true
|
| 10 |
+
kp2d_noise_scale: 0.5
|
| 11 |
+
perframe_condition_exists: true
|
| 12 |
+
train2d_mask_invis_obs: true
|
| 13 |
+
mask_occluded_imgfeats: true
|
| 14 |
+
cond_merge_strategy: "add"
|
| 15 |
+
use_cond_exists_as_input: true
|
| 16 |
+
normalize_cam_angvel: true
|
| 17 |
+
|
| 18 |
+
diffusion:
|
| 19 |
+
test_timestep_respacing: "50"
|
| 20 |
+
guidance_param: 2.5
|
| 21 |
+
|
| 22 |
+
text_encoder:
|
| 23 |
+
load_llm: false
|
| 24 |
+
llm_version: "t5-3b"
|
| 25 |
+
max_text_len: 50
|
| 26 |
+
|
| 27 |
+
condition_mask:
|
| 28 |
+
mask_img_prob: 0.5
|
| 29 |
+
mask_cam_prob: 1.0
|
| 30 |
+
reuse_regression_mask: false
|
| 31 |
+
regression_no_img_mask: true
|
| 32 |
+
|
| 33 |
+
mask_cfg:
|
| 34 |
+
drop_prob: 0.75
|
| 35 |
+
max_num_drops: 3
|
| 36 |
+
min_drop_nframes: 1
|
| 37 |
+
max_drop_nframes: 30
|
| 38 |
+
body_mask_cfg:
|
| 39 |
+
drop_prob: 0.75
|
| 40 |
+
joint_drop_prob: 0.25
|
| 41 |
+
max_num_drops: 3
|
| 42 |
+
min_drop_nframes: 1
|
| 43 |
+
max_drop_nframes: 30
|
| 44 |
+
music_mask_prob: 0.1
|
| 45 |
+
audio_mask_prob: 0.1
|
configs/network/diffusion.yaml
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: genmo.network.genmo_diffusion.GENMODiffusion
|
| 2 |
+
args: ${pipeline.args}
|
| 3 |
+
latent_dim: ${.model_cfg.denoiser.latent_dim}
|
| 4 |
+
cond_merge_strategy: "add"
|
| 5 |
+
music_mask_prob: ${.model_cfg.denoiser.music_mask_prob}
|
| 6 |
+
speech_mask_prob: ${.model_cfg.denoiser.speech_mask_prob}
|
| 7 |
+
encoded_music_dim: ${pipeline.args.encoded_music_dim}
|
| 8 |
+
model_cfg:
|
| 9 |
+
diffusion: ${model_cfg.diffusion}
|
| 10 |
+
denoiser:
|
| 11 |
+
_target_: genmo.network.genmo_denoiser.NetworkEncoderRoPE
|
| 12 |
+
output_dim: 151
|
| 13 |
+
xt_dim: ${.output_dim}
|
| 14 |
+
njoints: ${.xt_dim}
|
| 15 |
+
text_mask_prob: 0.1
|
| 16 |
+
music_mask_prob: 0.1
|
| 17 |
+
speech_mask_prob: 0.1
|
| 18 |
+
use_text_pos_enc: true
|
| 19 |
+
text_encoder_cfg:
|
| 20 |
+
mode: all
|
| 21 |
+
cross_attn_type: mha
|
| 22 |
+
latent_dim: 1024
|
| 23 |
+
num_layers: 16
|
| 24 |
+
num_heads: 8
|
| 25 |
+
mlp_ratio: 4
|
configs/optimizer/adamw_2e-4.yaml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: torch.optim.AdamW
|
| 2 |
+
lr: 2e-4
|
configs/optimizer/adamw_5e-5.yaml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: torch.optim.AdamW
|
| 2 |
+
lr: 5e-5
|
configs/pipeline/dual_mode.yaml
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: genmo.pipeline.genmo_pipeline.Pipeline
|
| 2 |
+
args_denoiser3d: ${network}
|
| 3 |
+
args:
|
| 4 |
+
endecoder_opt: ${endecoder}
|
| 5 |
+
use_regression_outputs_prob: 0.
|
| 6 |
+
use_cfg_sampler_for_gen: true
|
| 7 |
+
inpaint_x_start_gt: false
|
| 8 |
+
regression_only: true
|
| 9 |
+
encoded_music_dim: 35
|
| 10 |
+
multicond_args: ${multicond_args}
|
| 11 |
+
infer_version: 2
|
| 12 |
+
weights:
|
| 13 |
+
cr_j3d: 500.
|
| 14 |
+
transl_c: 1.
|
| 15 |
+
cr_verts: 500.
|
| 16 |
+
j2d: 1000.
|
| 17 |
+
j2d_17: 1000.
|
| 18 |
+
verts2d: 1000.
|
| 19 |
+
|
| 20 |
+
proj_gt_j2d_to_bi01: true
|
| 21 |
+
|
| 22 |
+
transl_w: 1.
|
| 23 |
+
static_conf_bce: 1.
|
| 24 |
+
|
| 25 |
+
static_conf:
|
| 26 |
+
vel_thr: 0.15
|
| 27 |
+
|
| 28 |
+
in_attr:
|
| 29 |
+
- obs
|
| 30 |
+
- f_cliffcam
|
| 31 |
+
- f_imgseq
|
| 32 |
+
- f_cam_angvel
|
| 33 |
+
- encoded_music
|
| 34 |
+
- encoded_audio
|
| 35 |
+
mask_out_attr: [] # ${.in_attr}
|
| 36 |
+
out_attr:
|
| 37 |
+
pred_cam: 3
|
configs/scheduler/cosine_50.yaml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
scheduler:
|
| 2 |
+
_target_: torch.optim.lr_scheduler.CosineAnnealingLR
|
| 3 |
+
T_max: 50
|
| 4 |
+
eta_min: 1e-6
|
| 5 |
+
interval: epoch
|
| 6 |
+
frequency: 1
|
configs/scheduler/epoch_half_200_350.yaml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
scheduler:
|
| 2 |
+
_target_: torch.optim.lr_scheduler.MultiStepLR
|
| 3 |
+
milestones: [200, 350]
|
| 4 |
+
gamma: 0.5
|
| 5 |
+
interval: epoch
|
| 6 |
+
frequency: 1
|
configs/test_datasets/3dpw_fliptest.yaml
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
3dpw_fliptest:
|
| 2 |
+
_target_: genmo.datasets.threedpw.threedpw_motion_test.ThreedpwSmplFullSeqDataset
|
| 3 |
+
flip_test: true
|
configs/test_datasets/3dpw_occ_fliptest.yaml
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
3dpw_occ_fliptest:
|
| 2 |
+
_target_: genmo.datasets.threedpw.threedpw_occ_motion_test.ThreedpwOccSmplFullSeqDataset
|
| 3 |
+
flip_test: true
|
configs/test_datasets/emdb1_fliptest.yaml
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
emdb1_fliptest:
|
| 2 |
+
_target_: genmo.datasets.emdb.emdb_motion_test.EmdbSmplFullSeqDataset
|
| 3 |
+
split: 1
|
| 4 |
+
flip_test: true
|
configs/test_datasets/emdb2_fliptest.yaml
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
emdb2_fliptest:
|
| 2 |
+
_target_: genmo.datasets.emdb.emdb_motion_test.EmdbSmplFullSeqDataset
|
| 3 |
+
split: 2
|
| 4 |
+
flip_test: true
|
configs/test_datasets/humanml3d_eval.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
humanml3d_eval:
|
| 2 |
+
_target_: genmo.datasets.pure_motion.humanml3d.Humanml3dDataset
|
| 3 |
+
eval_gen_only: true
|
| 4 |
+
cam_augmentation: v11
|
| 5 |
+
use_random_subset: true
|
| 6 |
+
random_subset_size: 2
|
| 7 |
+
random_subset_seed: 7
|
configs/test_datasets/rich_test.yaml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
rich_test:
|
| 2 |
+
_target_: genmo.datasets.rich.rich_motion_test.RichSmplFullSeqDataset
|