import argparse import json import os from pathlib import Path import numpy as np import torch from PIL import Image os.environ.setdefault("SPCONV_ALGO", "native") os.environ.setdefault("ATTN_BACKEND", "flash_attn") os.environ.setdefault("TOKENIZERS_PARALLELISM", "false") os.environ.setdefault("DVD_MODEL_REPO", "Zhengrui/dvd") def cfg_schedule(mode: str, constant: float, early: float, late: float, split: float): if mode == "Constant": return float(constant) if mode == "Two-stage": split = float(split) early = float(early) late = float(late) return lambda t: early if t < split else late return None def run_generate(config_path: str): with open(config_path, "r") as f: cfg = json.load(f) from dvd import DVDImageToVoxelPipeline, export_cubified_voxels repo = os.environ.get("DVD_MODEL_REPO", "Zhengrui/dvd") subfolder = os.environ.get("DVD_MODEL_SUBFOLDER") or None revision = os.environ.get("DVD_MODEL_REVISION") or None token = os.environ.get("DVD_MODEL_TOKEN") or os.environ.get("HF_TOKEN") or None print(f"[DVD Worker] loading DVD image pipeline from {repo}", flush=True) pipeline = DVDImageToVoxelPipeline.from_pretrained( repo, variant="base", device="cuda", subfolder=subfolder, revision=revision, token=token, ) print("[DVD Worker] pipeline ready", flush=True) image = Image.open(cfg["image_path"]).convert("RGBA") sampler_kwargs = {"steps": int(cfg["dvd_steps"])} schedule = cfg_schedule( cfg["dvd_cfg_mode"], float(cfg["dvd_cfg_constant"]), float(cfg["dvd_cfg_early"]), float(cfg["dvd_cfg_late"]), float(cfg["dvd_cfg_split"]), ) if schedule is not None: sampler_kwargs["cfg_strength"] = schedule print(f"[DVD Worker] sampling seed={cfg['seed']} steps={cfg['dvd_steps']}", flush=True) voxels = pipeline.sample_voxels( image, seed=int(cfg["seed"]), preprocess_image=bool(cfg["preprocess_image"]), **sampler_kwargs, ) mesh_path = cfg["mesh_path"] npy_path = cfg["npy_path"] export_cubified_voxels(voxels, mesh_path) np.save(npy_path, voxels.coords_without_batch.detach().cpu().numpy().astype(np.int32)) torch.cuda.empty_cache() print(f"[DVD Worker] done mesh={mesh_path} npy={npy_path}", flush=True) def main(): parser = argparse.ArgumentParser() parser.add_argument("command", choices=["generate"]) parser.add_argument("config") args = parser.parse_args() if args.command == "generate": run_generate(args.config) if __name__ == "__main__": main()