|
Download augment/vace/README.md from mlnha/pose6daug-scripts: direct link, hf CLI and curl.
- Browser
- Download file 10.6 kB
-
https://huggingface.co/mlnha/pose6daug-scripts/resolve/main/augment/vace/README.md
- Command line
-
hf download hf://mlnha/pose6daug-scripts/augment/vace/README.md
-
curl -L -o README.md https://huggingface.co/mlnha/pose6daug-scripts/resolve/main/augment/vace/README.md
10.6 kB
| # VACE augmentation β 8 objects Γ 32 episodes, 3 cameras | |
| Swaps a target mesh into RoboCasa episodes with the VACE video-diffusion model, producing | |
| the same folder layout as the MimicGen augmentation run so the two baselines can be | |
| compared file-for-file. | |
| **Same-category first, random for the remainder.** For `donut_5`, episodes that already | |
| contain a donut (`donut_8`, `donut_9`, β¦) are used first β those are the swaps VACE was | |
| designed for. Only after that pool runs out does the rest of the 32 come from randomly | |
| drawn episodes of any category (apple β donut_5, milk β donut_5, β¦). The split is recorded | |
| per assignment as `fill: same_category | random`. | |
| How far the same-category pool goes, after `make_gt_masks.py` filled in the 58 missing | |
| same-category masks (episodes with a complete set of GT masks, excluding the target mesh): | |
| | target | same-category pool | same-category used | random fill | reaches 32 same-category? | | |
| |---|---|---|---|---| | |
| | MeasuringCup009 | 57 | **32** | 0 | **yes** | | |
| | steak_8 | 18 | 18 | 14 | no | | |
| | SoapDispenser010 | 5 | 5 | 27 | no | | |
| | teapot_6 | 5 | 5 | 27 | no | | |
| | teapot_7 | 5 | 5 | 27 | no | | |
| | donut_5 | 3 | 3 | 29 | no | | |
| | Jar023 | 2 | 2 | 30 | no | | |
| | SyrupBottle005 | 2 | 2 | 30 | no | | |
| | **total** | | **72** | **184** | | | |
| Only MeasuringCup009 can be filled from its own category. This is a property of the | |
| dataset, not of the masks: across all 2,517 episodes there are only 5 teapot episodes, | |
| 3 donut, 2 jar, 2 syrup_bottle. Generating the other 1,830 missing masks would not move | |
| these numbers β only 58 of the 1,888 were same-category for these eight targets (55 | |
| measuring_cup, 3 steak), and those are already done. | |
| ## Run | |
| ```bash | |
| ./run_aug32.sh <work_dir> <out_dir> <gpu> [num_wan_workers] | |
| # one GPU | |
| ./run_aug32.sh /scratch/vace_aug32 \ | |
| /home/nvidia/minha/pose6daug/baseline/mimicgen/output_aug_256 2 | |
| # four GPUs: split-wan writes four manifests, one worker each | |
| ./run_aug32.sh /scratch/vace_aug32 /path/out 2 4 # then move the workers onto 4 GPUs by hand | |
| ``` | |
| Every stage is idempotent β re-running after an interruption resumes rather than redoing. | |
| | stage | what it does | cost | | |
| |---|---|---| | |
| | 1 `build` | pick sources, same-category first | seconds | | |
| | 2 `prep` | render the target mesh's reference views, cut frames, per-view manifests | ~4 s / assignment | | |
| | 3 `split` | chop into 81-frame WAN jobs | seconds | | |
| | 4 `wan` | the diffusion pass | **everything** | | |
| | 5 `stitch` | glue each camera's chunks back together | seconds | | |
| | 6 `collect` | copy into the output layout | seconds | | |
| **Runtime.** 256 assignments Γ 3 cameras β **3,084 WAN jobs**. At the measured 51.4 s/job | |
| that is **~44 h on one GPU**, ~11 h on four. Levers, in order of how much they buy and how | |
| little they cost: | |
| - `--offload_model False` is already passed by the script. The upstream default is `True` | |
| whenever `world_size == 1`, which moves the DiT to CPU and back around every job: 81.8 s | |
| vs 51.4 s measured. Never drop this flag. | |
| - `--sample_steps 25` (upstream default 50) β 32.1 s/job, ~27 h on one GPU. Quality | |
| trade-off; look at the plates before committing. | |
| - Dropping the two exo cameras cuts the job count to a third. At 256Γ256 the target-object | |
| mask is ~0.2 % of an exo frame and VACE tends to erase the object instead of replacing it; | |
| only `robot0_eye_in_hand` (~9 %) reliably gets a real swap. If the exo views are not | |
| needed, edit `CAMS` in `../vace_object_insert_batch.py`. | |
| ## Output | |
| ``` | |
| <out_dir>/<task>-ep<N>_<object the episode had>_<object it becomes>/ | |
| robot0_agentview_left/robot0_agentview_left.mp4 | |
| robot0_agentview_right/robot0_agentview_right.mp4 | |
| robot0_eye_in_hand/robot0_eye_in_hand.mp4 | |
| .done | |
| ``` | |
| e.g. `c2cab-ep000151_donut_donut_5` (same-category) and | |
| `snk2c-ep000004_egg_teapot_7` (random fill). Task tags are `c2cab`, `c2sto`, `drw2c`, | |
| `snk2c`, `tst2c`; the hyphen keeps the name to three underscore-separated parts, matching | |
| MimicGen's `ep098_apple_teapot_6`. `.done` carries the real task, episode, source mesh, | |
| target, language instruction, and which fill it came from. | |
| ## Files | |
| | file | | | |
| |---|---| | |
| | `build_aug32_assignments.py` | source selection β the only new logic | | |
| | `collect_outputs.py` | VACE plates β the output layout | | |
| | `run_aug32.sh` | all six stages | | |
| | `SETUP.md` | **start here on a new machine** β the setup path, in order | | |
| | `preflight.sh` | checks environments, weights, datasets, GT-mask coverage, GPU | | |
| | `make_gt_masks.py` | re-renders the missing GT masks from the simulator | | |
| | `vace_wan_inference_batch.patch` | the upstream diff, for porting onto a fresh clone | | |
| | `vendor/render_mesh_views_side.py` | mesh reference-view renderer, vendored from the original machine | | |
| Stages 2β5 are `../vace_object_insert_batch.py` and `../VACE/vace/vace_wan_inference.py` | |
| unmodified; this directory adds selection and collection around them. | |
| ## Prerequisites | |
| Run `./preflight.sh` β it checks every item below and prints GT-mask coverage and GPU | |
| state. Nothing here needs to be installed or cloned; it all already exists on this box and | |
| is referenced by absolute path, the same convention the other baselines use. | |
| ### Environments (do NOT create a venv) | |
| | what | python | | |
| |---|---| | |
| | batch driver (`vace_object_insert_batch.py`, the builder, the collector) | `/lp-dev/jonghoon/robocasa_calib/envs/robocasa/bin/python` (3.10, mujoco + robocasa) | | |
| | WAN inference | `/lp-dev/jonghoon/VACE/venv/bin/python` (3.12, torch 2.5.1+cu124, flash_attn 2.8.3) | | |
| | mesh reference-view rendering (called by `prep-worker`) | `/lp-dev/jonghoon/isaac-gr00t/venv/bin/python` β override with `VACE_RENDER_PYTHON`; it only needs `trimesh`, `pyrender`, `numpy`, `pillow` (measured: 4.12.1 / 0.1.45 / 1.26.4 / 12.1.1), so any env with those will do | | |
| `prep-worker` renders the target mesh's reference views by importing `render_views` from | |
| `render_mesh_views_side.py`, which lived outside this tree on the original machine. A copy | |
| ships in **`vendor/render_mesh_views_side.py`**; point at it with | |
| ```bash | |
| export VACE_RENDER_SCRIPT_DIR=$PWD/aug32/vendor | |
| export VACE_RENDER_PYTHON=/path/to/a/python/with/trimesh+pyrender | |
| ``` | |
| ### VACE code and weights (already cloned β do NOT clone again) | |
| `../VACE/` is a fork of `https://github.com/ali-vilab/VACE.git` carrying the batch flags | |
| (`--batch_manifest / --skip_existing / --batch_continue_on_error`) this pipeline depends on; | |
| a fresh upstream clone will not have them. Weights come in through | |
| `../VACE/models -> /lp-dev/jonghoon/VACE-home-models` (31 GB: `Wan2.1-VACE-1.3B`, | |
| `VACE-Annotators`). ~27 GB of GPU memory is needed with `--offload_model False`. | |
| ### Datasets | |
| | path | what | | |
| |---|---| | |
| | `/home/nvidia/jonghoon/robocasa_full/pickplace_target_human/` | source episodes β `videos/chunk-000/observation.images.<camera>/episode_NNNNNN.mp4` and `extras/episode_NNNNNN/ep_meta.json` (symlink to `/lp-dev/...`) | | |
| | `/home/nvidia/jonghoon/robocasa_full/aug_materials/robocasa/<task>/ep<N>/` | `mask_gt_target_object_<camera>.mp4` β the GT masks | | |
| | `/lp-dev/jonghoon/robocasa_calib/repos/robocasa/robocasa/models/assets/objects/{objaverse,lightwheel}/` | target meshes | | |
| GT-mask coverage, measured: `PickPlaceCounterToCabinet` 502, `CounterToStove` 50, | |
| `DrawerToCounter` 43, `SinkToCounter` 34, `ToasterToCounter` 0 β 629 usable episodes, and | |
| the builder draws only from those. | |
| ## Porting to another machine | |
| Do **not** clone `ali-vilab/VACE` fresh β upstream has no `--batch_manifest`, which every | |
| stage past `split-wan` depends on. | |
| **Copy the whole `baseline/vace/` directory**, not just `aug32/`. Nothing outside it is | |
| needed except the 31 GB of WAN weights. To rebuild from a clone instead: | |
| `git clone https://github.com/ali-vilab/VACE.git && git checkout 48eb44f`, then | |
| `git apply vace_wan_inference_batch.patch`, and copy `build_vace_wan_batch_manifest.py`, | |
| `vace_inference_full.py` and this `aug32/` directory alongside it. | |
| ### Unpack the data | |
| ```bash | |
| cd baseline/vace && mkdir -p data && cd data | |
| tar -xf ../datasets_pack/source_episodes.tar # 2.7 GB -> pickplace_target_human/ | |
| tar -xzf ../datasets_pack/aug_materials_ext.tar.gz # 121 MB -> aug_materials_ext/ | |
| tar -xzf ../datasets_pack/target_meshes.tar.gz # 14 MB -> objaverse/, lightwheel/ | |
| cd .. | |
| ``` | |
| ### Point everything at it | |
| Every path is an environment variable with the original machine's value as the default, so | |
| this is the whole configuration: | |
| | variable | default | set it to | | |
| |---|---|---| | |
| | `VACE_ROBOCASA_ROOT` | original machine | `$PWD/data/pickplace_target_human` | | |
| | `VACE_AUG_MATERIALS` | original machine | `$PWD/data/aug_materials_ext` | | |
| | `VACE_ASSET_ROOTS` | original machine | `$PWD/data/lightwheel:$PWD/data/objaverse` | | |
| | `VACE_PY_ROBOCASA` | original machine | a python with `robocasa`, `mujoco`, `trimesh`, `pyrender` | | |
| | `VACE_PY_WAN` | original machine | a python with torch 2.5.1+cu124 and `flash_attn` | | |
| | `VACE_RENDER_SCRIPT_DIR` | **`aug32/vendor/`** | β already inside the tree | | |
| | `VACE_RENDER_PYTHON` | **`VACE_PY_ROBOCASA`** | β only if that env lacks trimesh/pyrender | | |
| ```bash | |
| export VACE_ROBOCASA_ROOT=$PWD/data/pickplace_target_human | |
| export VACE_AUG_MATERIALS=$PWD/data/aug_materials_ext | |
| export VACE_ASSET_ROOTS=$PWD/data/lightwheel:$PWD/data/objaverse | |
| export VACE_PY_ROBOCASA=/path/to/robocasa/python | |
| export VACE_PY_WAN=/path/to/wan/python | |
| ./aug32/preflight.sh # says MISS for anything still wrong | |
| ``` | |
| The mesh reference-view renderer (`render_mesh_views_side.py`, which `prep-worker` imports) | |
| is vendored at `aug32/vendor/` and defaults to the driver's own interpreter, so it needs no | |
| separate environment β `trimesh` and `pyrender` are its only requirements beyond numpy/PIL. | |
| ### Still needed from elsewhere | |
| The 31 GB of WAN weights (`Wan2.1-VACE-1.3B`, `VACE-Annotators`) β link them in at | |
| `VACE/models`. And, only if you want to re-run `make_gt_masks.py` there, the meshes of | |
| objects other than the eight targets, since that rebuilds each episode's own scene. | |
| ### Gotchas | |
| - An episode without GT masks makes `prep-worker` raise `FileNotFoundError`. The builder | |
| filters on this, so it cannot happen through `run_aug32.sh` β but it will if you hand-edit | |
| `assignments.jsonl`. | |
| - The WAN stage must run with `vace/VACE` as the working directory (imports and `--ckpt_dir` | |
| are relative to it). `run_aug32.sh` does the `cd`. | |
| - `--save_file` in `vace_wan_inference.py` is written relative to the *current* directory, | |
| not `--save_dir`. The batch path does not use it; a one-off call should pass an absolute | |
| path. | |