Download forgebench/code/ours/dump_seed.py from Ronaldo-GOAT/bert_simpson: direct link, hf CLI and curl.
- Browser
- Download file 8.1 kB
-
https://huggingface.co/Ronaldo-GOAT/bert_simpson/resolve/main/forgebench/code/ours/dump_seed.py
- Command line
-
hf download hf://Ronaldo-GOAT/bert_simpson/forgebench/code/ours/dump_seed.py
-
curl -L -o dump_seed.py https://huggingface.co/Ronaldo-GOAT/bert_simpson/resolve/main/forgebench/code/ours/dump_seed.py
8.1 kB
| #!/usr/bin/env python | |
| """PASS 1 (REFERENCE ENV) — dump the ORACLE-VISIBILITY SS seed latent z1. | |
| Three-pass SSFlow eval driver, pass 1 of 3: | |
| dump_seed.py (reference env, production sam3d_objects) -> z1 per object | |
| ssflow_coords.py (TRAINING repo, vendored sam3d_objects) -> coords per object | |
| finish_cache.py (reference env) -> the stage-1 npz cache | |
| WHY THREE PROCESSES: ``tools/val_stage1_ref.py`` deliberately pops PYTHONPATH so | |
| that the PRODUCTION ``sam3d_objects`` (/lp-dev/jonghoon/mv-mesh/mv-sam3d) is | |
| imported. The trained ``SSFlowModel`` lives in the TRAINING repo's vendored | |
| ``sam3d_objects``. Importing both in one interpreter is unsafe, so the pipeline | |
| is split and the two sides only exchange .npz files. | |
| WHAT THIS SCRIPT DOES — steps 1-4 of ``val_stage1_ref.stage1_and_seed()``, | |
| BYTE-IDENTICAL: | |
| 1. loads the input view PNGs ``EXP/inputs/<obj>_<tag>.png`` (existence + | |
| decodability check; they have NO numerical effect on z1 — in the reference | |
| they feed only the SS-generator conditioning, which is exactly the part | |
| pass 2 replaces). | |
| 2. ``gt_vis, gt_full, free = baf.load_gt_synth(Path(exp), obj, views_tags, n=baf.VOX)`` | |
| 3. ``rng = np.random.default_rng(seed); occ = baf.build_input_grid(gt_vis, free, "zeros", rng)`` | |
| -- the 64^3 ORACLE-VISIBILITY seed, union over the input views. | |
| 4. ``z1 = baf.grid_to_shape_latent(ss_enc, occ)`` -- the SS-encoded partial | |
| occupancy == ``z_partial``. | |
| Lines 2-4 are the reference block verbatim; ``noise="zeros"`` consumes nothing | |
| from ``rng``, so z1 is a deterministic function of (exp, obj, views). | |
| DELIBERATE DEVIATION (documented): the reference builds the WHOLE | |
| ``baf.Models()`` (production Inference pipeline + SLAT encoder + DINO). z1 needs | |
| only ``baf.load_ss_encoder()``, so that is all we build. ``grid_to_shape_latent`` | |
| is a pure function of (ss_enc, occ), so the dumped z1 is bit-identical to the | |
| reference's -- just ~100x cheaper to produce. The da3 pointmaps | |
| (``npz_{n}v/<obj>/da3_output.npz``) are NOT read: they only feed the SS | |
| conditioning that pass 2 replaces. | |
| Output: ``<out>/<obj>.npz`` with | |
| z1 (1,4096,8) float32 exactly as grid_to_shape_latent produced it | |
| occ (64,64,64) uint8 the partial-occupancy grid, for the record | |
| views (V,) str, seed int | |
| Launch (re-execs itself into the reference env; caller sets CUDA_VISIBLE_DEVICES | |
| to ONE gpu -- baf.DEVICE is hardcoded 'cuda'): | |
| CUDA_VISIBLE_DEVICES=7 python dump_seed.py \ | |
| --exp /lp-dev/jonghoon/mv-mesh/exp_faithfulness/toys4k100_tex \ | |
| --views 2 --out /lp-dev/jonghoon/ss_flow_data/eval_20260916/seed/toys4k100_tex/2v | |
| """ | |
| import os | |
| import sys | |
| ENV_PY = "/lp-dev/jonghoon/mv-mesh/envs/mv-sam3d/bin/python" | |
| ENV = "/lp-dev/jonghoon/mv-mesh/envs/mv-sam3d" | |
| MVMESH = "/lp-dev/jonghoon/mv-mesh" | |
| METRICS_DIR = os.path.join(MVMESH, "metrics") | |
| # --- re-exec preamble: VERBATIM from tools/val_stage1_ref.py ----------------- | |
| if not os.environ.get("_VAL_STAGE1_INENV"): | |
| env = dict(os.environ) | |
| env["_VAL_STAGE1_INENV"] = "1" | |
| env["_APPFORCE_SAM3D_INENV"] = "1" # batch_appforce must not re-exec | |
| env.pop("PYTHONPATH", None) # never the training repo's sam3d_objects | |
| env["PATH"] = os.path.join(ENV, "bin") + os.pathsep + env.get("PATH", "") | |
| assert env.get("CUDA_VISIBLE_DEVICES"), "set CUDA_VISIBLE_DEVICES to one GPU" | |
| os.execve(ENV_PY, [ENV_PY, os.path.abspath(__file__)] + sys.argv[1:], env) | |
| os.environ["_APPFORCE_SAM3D_INENV"] = "1" | |
| sys.path.insert(0, METRICS_DIR) | |
| import batch_appforce_sam3d as baf # noqa: E402 (chdir REPO, sys.path, env defaults) | |
| import argparse # noqa: E402 | |
| import json # noqa: E402 | |
| import time # noqa: E402 | |
| import traceback # noqa: E402 | |
| from pathlib import Path # noqa: E402 | |
| import numpy as np # noqa: E402 | |
| import torch # noqa: E402 | |
| from PIL import Image # noqa: E402 | |
| # --- VIEW TAG TABLE: verbatim from tools/val_stage1_ref.py ------------------ | |
| VIEW_TAGS = ["front", "side", "back", "oside", "top", "bottom", "top2", "bottom2"] | |
| def views_tags_for(n: int): | |
| assert 1 <= n <= len(VIEW_TAGS), f"--views {n} unsupported (max {len(VIEW_TAGS)})" | |
| return VIEW_TAGS[:n] | |
| def _objects(args): | |
| """Verbatim from tools/val_stage1_ref.py::_objects.""" | |
| if args.objects_file: | |
| objs = [l.strip() for l in open(args.objects_file) if l.strip()] | |
| elif args.objects: | |
| objs = list(args.objects) | |
| else: | |
| data = json.loads(Path(os.path.join(args.exp, "selection.json")).read_text()) | |
| sels = data["selections"] if isinstance(data, dict) else data | |
| objs = [s["object"] for s in sels] | |
| if args.limit: | |
| objs = objs[: args.limit] | |
| if args.nshards > 1: | |
| objs = objs[args.shard::args.nshards] | |
| return objs | |
| def seed_for_object(ss_enc, obj, exp, inputs_dir, views_tags, seed): | |
| """Steps 1-4 of val_stage1_ref.stage1_and_seed, unchanged.""" | |
| # ---- step 1 (verbatim; existence/decodability check only) -------------- | |
| for t in views_tags: | |
| p = os.path.join(inputs_dir, f"{obj}_{t}.png") | |
| if not os.path.isfile(p): | |
| raise FileNotFoundError(p) | |
| np.array(Image.open(p).convert("RGBA")) | |
| # ---- steps 2-4 (verbatim) ---------------------------------------------- | |
| gt_vis, gt_full, free = baf.load_gt_synth(Path(exp), obj, views_tags, n=baf.VOX) | |
| rng = np.random.default_rng(seed) | |
| occ = baf.build_input_grid(gt_vis, free, "zeros", rng) | |
| z1 = baf.grid_to_shape_latent(ss_enc, occ) | |
| return dict(z1=z1.detach().float().cpu().numpy(), # (1,4096,8) float32 | |
| occ=(occ > 0.5).astype(np.uint8)) # (64,64,64) uint8 | |
| def main(): | |
| ap = argparse.ArgumentParser(description=__doc__, | |
| formatter_class=argparse.RawDescriptionHelpFormatter) | |
| ap.add_argument("--exp", required=True, | |
| help="EXPDIR (renders/, inputs/, selection.json)") | |
| ap.add_argument("--views", type=int, default=2, | |
| help="number of condition views (1..8); tags = VIEW_TAGS[:views]") | |
| ap.add_argument("--out", required=True, help="seed dump dir (<obj>.npz each)") | |
| ap.add_argument("--seed", type=int, default=42) | |
| ap.add_argument("--objects", nargs="+", default=None) | |
| ap.add_argument("--objects-file", default=None) | |
| ap.add_argument("--limit", type=int, default=0) | |
| ap.add_argument("--shard", type=int, default=0) | |
| ap.add_argument("--nshards", type=int, default=1) | |
| ap.add_argument("--force", action="store_true") | |
| args = ap.parse_args() | |
| exp = os.path.abspath(args.exp) | |
| inputs_dir = os.path.join(exp, "inputs") | |
| views_tags = views_tags_for(args.views) | |
| out = Path(args.out) | |
| out.mkdir(parents=True, exist_ok=True) | |
| objs = _objects(args) | |
| print(f"[seed] exp={exp} views={args.views} n_obj={len(objs)} " | |
| f"shard={args.shard}/{args.nshards} seed={args.seed} " | |
| f"CUDA={os.environ.get('CUDA_VISIBLE_DEVICES')}", flush=True) | |
| t0 = time.time() | |
| ss_enc = baf.load_ss_encoder() | |
| print(f"[seed] ss_encoder ready {time.time() - t0:.1f}s", flush=True) | |
| n_ok = n_fail = n_skip = 0 | |
| for i, obj in enumerate(objs, 1): | |
| f = out / f"{obj}.npz" | |
| if f.is_file() and not args.force: | |
| n_skip += 1 | |
| continue | |
| t1 = time.time() | |
| try: | |
| d = seed_for_object(ss_enc, obj, exp, inputs_dir, views_tags, args.seed) | |
| tmp = str(f) + ".tmp.npz" | |
| np.savez_compressed(tmp, **d, views=np.array(views_tags), seed=args.seed) | |
| os.replace(tmp, f) | |
| n_ok += 1 | |
| print(f"[seed {i}/{len(objs)}] OK {obj} occ={int(d['occ'].sum())} " | |
| f"z1={d['z1'].shape} {time.time() - t1:.1f}s", flush=True) | |
| except Exception: | |
| n_fail += 1 | |
| traceback.print_exc() | |
| print(f"[seed {i}/{len(objs)}] FAIL {obj}", flush=True) | |
| torch.cuda.empty_cache() | |
| print(f"DUMPSEED DONE ok={n_ok} fail={n_fail} skip={n_skip} total={len(objs)}", | |
| flush=True) | |
| if __name__ == "__main__": | |
| main() | |