Publish evaluated Forma3D-Tiny v0.2
Browse files- ATTRIBUTIONS.json +1314 -0
- COMMANDS.md +110 -0
- DATASETS.md +32 -0
- LICENSE +202 -0
- NOTICE +11 -0
- README.md +68 -0
- SHA256SUMS +26 -0
- THIRD_PARTY.md +13 -0
- config.json +4 -0
- evaluation.json +38 -0
- licenses/Idol-APACHE-2.0.txt +202 -0
- model.pt +3 -0
- pyproject.toml +28 -0
- requirements-tested-macos.txt +32 -0
- scripts/prepare_hf.py +463 -0
- scripts/release.py +228 -0
- setup-mac.sh +15 -0
- src/image3d_student/__init__.py +5 -0
- src/image3d_student/cli.py +126 -0
- src/image3d_student/data.py +149 -0
- src/image3d_student/demo.py +31 -0
- src/image3d_student/engine.py +204 -0
- src/image3d_student/model.py +76 -0
- src/image3d_student/splats.py +108 -0
- src/image3d_student/teacher_idol.py +141 -0
- train-mac.sh +44 -0
- training.json +366 -0
ATTRIBUTIONS.json
ADDED
|
@@ -0,0 +1,1314 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"repo": "scenario-labs/3d-collection",
|
| 4 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 5 |
+
"path": "assets/scenario_asset_j69T8oBpnATHCfYAAaa9tHQm/output.glb",
|
| 6 |
+
"sha256": "5a99d51a3a1765cddffb545fb80970bda9eb83ca64382788bd064ff8239782d7",
|
| 7 |
+
"asset_id": "scenario:asset_j69T8oBpnATHCfYAAaa9tHQm",
|
| 8 |
+
"license": "cc-by-4.0",
|
| 9 |
+
"author": "Scenario",
|
| 10 |
+
"title": "scenario:asset_j69T8oBpnATHCfYAAaa9tHQm",
|
| 11 |
+
"source_model": "model_scenario-claude-opus-5-5-3d",
|
| 12 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 13 |
+
"object_id": "scenario-0f2e19a4898f95756a1a",
|
| 14 |
+
"source_object_id": "scenario-0f2e19a4898f95756a1a"
|
| 15 |
+
},
|
| 16 |
+
{
|
| 17 |
+
"repo": "scenario-labs/3d-collection",
|
| 18 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 19 |
+
"path": "assets/scenario_asset_j5kkiUz5G8bpJX78kwkJCvZs/output.glb",
|
| 20 |
+
"sha256": "8c9121b558f19a067aa76a6940c98252765ef79b45d651e922d99ffc8f23f44f",
|
| 21 |
+
"asset_id": "scenario:asset_j5kkiUz5G8bpJX78kwkJCvZs",
|
| 22 |
+
"license": "cc-by-4.0",
|
| 23 |
+
"author": "Scenario",
|
| 24 |
+
"title": "scenario:asset_j5kkiUz5G8bpJX78kwkJCvZs",
|
| 25 |
+
"source_model": "model_pixal3d",
|
| 26 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 27 |
+
"object_id": "scenario-63ee5f1041b51dbdca56",
|
| 28 |
+
"source_object_id": "scenario-63ee5f1041b51dbdca56"
|
| 29 |
+
},
|
| 30 |
+
{
|
| 31 |
+
"repo": "scenario-labs/3d-collection",
|
| 32 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 33 |
+
"path": "assets/scenario_asset_ecawy76SCymJthaVd38SvNPT/output.glb",
|
| 34 |
+
"sha256": "871a1cc7bbe5ea9605d31f6f9c213696c202c51ace4fedd6114c4535b616ea4d",
|
| 35 |
+
"asset_id": "scenario:asset_ecawy76SCymJthaVd38SvNPT",
|
| 36 |
+
"license": "cc-by-4.0",
|
| 37 |
+
"author": "Scenario",
|
| 38 |
+
"title": "scenario:asset_ecawy76SCymJthaVd38SvNPT",
|
| 39 |
+
"source_model": "model_tripo-v2-5-image-to-3d",
|
| 40 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 41 |
+
"object_id": "scenario-cddc1d43d8bf54b84aeb",
|
| 42 |
+
"source_object_id": "scenario-cddc1d43d8bf54b84aeb"
|
| 43 |
+
},
|
| 44 |
+
{
|
| 45 |
+
"repo": "scenario-labs/3d-collection",
|
| 46 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 47 |
+
"path": "assets/scenario_asset_uKgWMW27HVuHYKfb21S9pP1V/output.glb",
|
| 48 |
+
"sha256": "d67442b0ad2828b743efa43058e0a773521dd53b1c92ba4e8e445e4f4f198e23",
|
| 49 |
+
"asset_id": "scenario:asset_uKgWMW27HVuHYKfb21S9pP1V",
|
| 50 |
+
"license": "cc-by-4.0",
|
| 51 |
+
"author": "Scenario",
|
| 52 |
+
"title": "scenario:asset_uKgWMW27HVuHYKfb21S9pP1V",
|
| 53 |
+
"source_model": "model_scenario-gpt6-astra-3d",
|
| 54 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 55 |
+
"object_id": "scenario-149583b9bacab13e8588",
|
| 56 |
+
"source_object_id": "scenario-149583b9bacab13e8588"
|
| 57 |
+
},
|
| 58 |
+
{
|
| 59 |
+
"repo": "scenario-labs/3d-collection",
|
| 60 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 61 |
+
"path": "assets/scenario_asset_xyRDpvBmjLJKoZtU8utx9gRH/output.glb",
|
| 62 |
+
"sha256": "6695720343b20ee12e87a196becbf8aca22463c7b725b42571fae32ef1c6fd57",
|
| 63 |
+
"asset_id": "scenario:asset_xyRDpvBmjLJKoZtU8utx9gRH",
|
| 64 |
+
"license": "cc-by-4.0",
|
| 65 |
+
"author": "Scenario",
|
| 66 |
+
"title": "scenario:asset_xyRDpvBmjLJKoZtU8utx9gRH",
|
| 67 |
+
"source_model": "model_tripo-v2-5-image-to-3d",
|
| 68 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 69 |
+
"object_id": "scenario-74b4c6a58a7a9fd27185",
|
| 70 |
+
"source_object_id": "scenario-74b4c6a58a7a9fd27185"
|
| 71 |
+
},
|
| 72 |
+
{
|
| 73 |
+
"repo": "scenario-labs/3d-collection",
|
| 74 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 75 |
+
"path": "assets/scenario_asset_Lfd5tqLimGQtrD7ifXzKcmjG/output.glb",
|
| 76 |
+
"sha256": "32d6fab78c142a58a462a3a28bc4f03eded415e5553a1177f4c487cc25ec8d9f",
|
| 77 |
+
"asset_id": "scenario:asset_Lfd5tqLimGQtrD7ifXzKcmjG",
|
| 78 |
+
"license": "cc-by-4.0",
|
| 79 |
+
"author": "Scenario",
|
| 80 |
+
"title": "scenario:asset_Lfd5tqLimGQtrD7ifXzKcmjG",
|
| 81 |
+
"source_model": "model_rodin-hyper3d",
|
| 82 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 83 |
+
"object_id": "scenario-5a5f6e10b1f1d1adb638",
|
| 84 |
+
"source_object_id": "scenario-5a5f6e10b1f1d1adb638"
|
| 85 |
+
},
|
| 86 |
+
{
|
| 87 |
+
"repo": "scenario-labs/3d-collection",
|
| 88 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 89 |
+
"path": "assets/scenario_asset_8i2h2wUfLzme7LUYLWU5AWDv/output.glb",
|
| 90 |
+
"sha256": "598e38def4f3868c7b9782daae80a462b759f4ad2f6abf074b5c22f435521acb",
|
| 91 |
+
"asset_id": "scenario:asset_8i2h2wUfLzme7LUYLWU5AWDv",
|
| 92 |
+
"license": "cc-by-4.0",
|
| 93 |
+
"author": "Scenario",
|
| 94 |
+
"title": "scenario:asset_8i2h2wUfLzme7LUYLWU5AWDv",
|
| 95 |
+
"source_model": "model_trellis",
|
| 96 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 97 |
+
"object_id": "scenario-d7e8f8b03a4a6207bc64",
|
| 98 |
+
"source_object_id": "scenario-d7e8f8b03a4a6207bc64"
|
| 99 |
+
},
|
| 100 |
+
{
|
| 101 |
+
"repo": "scenario-labs/3d-collection",
|
| 102 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 103 |
+
"path": "assets/scenario_asset_GN2PtfF8pL61mgLoYHPMs2Ns/output.glb",
|
| 104 |
+
"sha256": "d8ff52ff8eb4c2dcf1b67e89979d1e66eccb069f404d6b9e75b84221e4830392",
|
| 105 |
+
"asset_id": "scenario:asset_GN2PtfF8pL61mgLoYHPMs2Ns",
|
| 106 |
+
"license": "cc-by-4.0",
|
| 107 |
+
"author": "Scenario",
|
| 108 |
+
"title": "scenario:asset_GN2PtfF8pL61mgLoYHPMs2Ns",
|
| 109 |
+
"source_model": "model_meshy-txt23d",
|
| 110 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 111 |
+
"object_id": "scenario-8e7c4a687ffbe178d8d7",
|
| 112 |
+
"source_object_id": "scenario-8e7c4a687ffbe178d8d7"
|
| 113 |
+
},
|
| 114 |
+
{
|
| 115 |
+
"repo": "scenario-labs/3d-collection",
|
| 116 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 117 |
+
"path": "assets/scenario_asset_PxbXeyqvNysMiYub8zn3C2eR/output.glb",
|
| 118 |
+
"sha256": "40be851ac7ceacaf3cad1227e0a65ff5da312769a7f4a4f0865fc80878a18bb9",
|
| 119 |
+
"asset_id": "scenario:asset_PxbXeyqvNysMiYub8zn3C2eR",
|
| 120 |
+
"license": "cc-by-4.0",
|
| 121 |
+
"author": "Scenario",
|
| 122 |
+
"title": "scenario:asset_PxbXeyqvNysMiYub8zn3C2eR",
|
| 123 |
+
"source_model": "model_meshy-7-1-img23d",
|
| 124 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 125 |
+
"object_id": "scenario-8a32f2baa95a557b9d61",
|
| 126 |
+
"source_object_id": "scenario-8a32f2baa95a557b9d61"
|
| 127 |
+
},
|
| 128 |
+
{
|
| 129 |
+
"repo": "scenario-labs/3d-collection",
|
| 130 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 131 |
+
"path": "assets/scenario_asset_odL4YXhQCEFB3NwywcT6W9LV/output.glb",
|
| 132 |
+
"sha256": "6d942ea2f2b3115a33ceb4510fe32461e0d152612d7f80563695e23600fd2fbb",
|
| 133 |
+
"asset_id": "scenario:asset_odL4YXhQCEFB3NwywcT6W9LV",
|
| 134 |
+
"license": "cc-by-4.0",
|
| 135 |
+
"author": "Scenario",
|
| 136 |
+
"title": "scenario:asset_odL4YXhQCEFB3NwywcT6W9LV",
|
| 137 |
+
"source_model": "model_reconviagen-0-5",
|
| 138 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 139 |
+
"object_id": "scenario-34ba20395fdf508cd9cc",
|
| 140 |
+
"source_object_id": "scenario-34ba20395fdf508cd9cc"
|
| 141 |
+
},
|
| 142 |
+
{
|
| 143 |
+
"repo": "scenario-labs/3d-collection",
|
| 144 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 145 |
+
"path": "assets/75f5c6b128053234/6e44e427eff9329f.glb",
|
| 146 |
+
"sha256": "a15e441f40d6b36c61bdfcc665f4aed4c01b108998e00b8ee1ad261d6cf39271",
|
| 147 |
+
"asset_id": "75f5c6b128053234",
|
| 148 |
+
"license": "cc-by-4.0",
|
| 149 |
+
"author": "Scenario",
|
| 150 |
+
"title": "75f5c6b128053234",
|
| 151 |
+
"source_model": "gpt-6-astra",
|
| 152 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 153 |
+
"object_id": "scenario-5b9e2bb00fd7fde9af1e",
|
| 154 |
+
"source_object_id": "scenario-5b9e2bb00fd7fde9af1e"
|
| 155 |
+
},
|
| 156 |
+
{
|
| 157 |
+
"repo": "scenario-labs/3d-collection",
|
| 158 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 159 |
+
"path": "assets/scenario_asset_GPuZMdobUQDpkGtBzDfoEvnU/output.glb",
|
| 160 |
+
"sha256": "881c8f3e5de7478d46efd0fbaf1bc91062d9f1dd6805ab63eee8b7a7b106a5e1",
|
| 161 |
+
"asset_id": "scenario:asset_GPuZMdobUQDpkGtBzDfoEvnU",
|
| 162 |
+
"license": "cc-by-4.0",
|
| 163 |
+
"author": "Scenario",
|
| 164 |
+
"title": "scenario:asset_GPuZMdobUQDpkGtBzDfoEvnU",
|
| 165 |
+
"source_model": "model_tripo-p1-multiview-to-3d",
|
| 166 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 167 |
+
"object_id": "scenario-ade571817876d8668a6e",
|
| 168 |
+
"source_object_id": "scenario-ade571817876d8668a6e"
|
| 169 |
+
},
|
| 170 |
+
{
|
| 171 |
+
"repo": "scenario-labs/3d-collection",
|
| 172 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 173 |
+
"path": "assets/scenario_asset_eTuW5Zb3UH1tnPFfpf62eEJf/output.glb",
|
| 174 |
+
"sha256": "30e63f0028f5e08dc6e7f94546f47630a77993b5bdcc0f9129c58ecf16306f0a",
|
| 175 |
+
"asset_id": "scenario:asset_eTuW5Zb3UH1tnPFfpf62eEJf",
|
| 176 |
+
"license": "cc-by-4.0",
|
| 177 |
+
"author": "Scenario",
|
| 178 |
+
"title": "scenario:asset_eTuW5Zb3UH1tnPFfpf62eEJf",
|
| 179 |
+
"source_model": "model_tripo-p1-multiview-to-3d",
|
| 180 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 181 |
+
"object_id": "scenario-466d0be00c0e012fb542",
|
| 182 |
+
"source_object_id": "scenario-466d0be00c0e012fb542"
|
| 183 |
+
},
|
| 184 |
+
{
|
| 185 |
+
"repo": "scenario-labs/3d-collection",
|
| 186 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 187 |
+
"path": "assets/scenario_asset_pULm1d2Z2udMAY1oUnhVckjr/output.glb",
|
| 188 |
+
"sha256": "e5fc737f3e8e00b25c926777a3062c227e017d14d9126283ee3b10040126fb49",
|
| 189 |
+
"asset_id": "scenario:asset_pULm1d2Z2udMAY1oUnhVckjr",
|
| 190 |
+
"license": "cc-by-4.0",
|
| 191 |
+
"author": "Scenario",
|
| 192 |
+
"title": "scenario:asset_pULm1d2Z2udMAY1oUnhVckjr",
|
| 193 |
+
"source_model": "model_csm-multiview-to-3d",
|
| 194 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 195 |
+
"object_id": "scenario-d147580bd3107d1a4eb8",
|
| 196 |
+
"source_object_id": "scenario-d147580bd3107d1a4eb8"
|
| 197 |
+
},
|
| 198 |
+
{
|
| 199 |
+
"repo": "scenario-labs/3d-collection",
|
| 200 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 201 |
+
"path": "assets/scenario_asset_6wkTbVyWTk8kTaFA36P7eXLK/output.glb",
|
| 202 |
+
"sha256": "00923c07b521a7cd3d16904204c55e67a7a15e855001f9fa16677411d9bdfb21",
|
| 203 |
+
"asset_id": "scenario:asset_6wkTbVyWTk8kTaFA36P7eXLK",
|
| 204 |
+
"license": "cc-by-4.0",
|
| 205 |
+
"author": "Scenario",
|
| 206 |
+
"title": "scenario:asset_6wkTbVyWTk8kTaFA36P7eXLK",
|
| 207 |
+
"source_model": "model_hitem-3d-3-0",
|
| 208 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 209 |
+
"object_id": "scenario-466d0be00c0e012fb542",
|
| 210 |
+
"source_object_id": "scenario-466d0be00c0e012fb542"
|
| 211 |
+
},
|
| 212 |
+
{
|
| 213 |
+
"repo": "scenario-labs/3d-collection",
|
| 214 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 215 |
+
"path": "assets/scenario_asset_fXLLwifmNEiarzDHvU9qR9c6/output.glb",
|
| 216 |
+
"sha256": "8a5c966299b8ba69a36afcf86164606b9d5e2c0dda209c668180396721c1b80f",
|
| 217 |
+
"asset_id": "scenario:asset_fXLLwifmNEiarzDHvU9qR9c6",
|
| 218 |
+
"license": "cc-by-4.0",
|
| 219 |
+
"author": "Scenario",
|
| 220 |
+
"title": "scenario:asset_fXLLwifmNEiarzDHvU9qR9c6",
|
| 221 |
+
"source_model": "model_rodin-hyper3d-v2-5",
|
| 222 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 223 |
+
"object_id": "scenario-b5f455653965ad70ef61",
|
| 224 |
+
"source_object_id": "scenario-b5f455653965ad70ef61"
|
| 225 |
+
},
|
| 226 |
+
{
|
| 227 |
+
"repo": "scenario-labs/3d-collection",
|
| 228 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 229 |
+
"path": "assets/scenario_asset_jXUrm3QeKHsQSzwaRAVpAdNn/output.glb",
|
| 230 |
+
"sha256": "0ab33363f3b705073b28486e9f795cef48ee3931f21cf3d8d9232fa0f5062c86",
|
| 231 |
+
"asset_id": "scenario:asset_jXUrm3QeKHsQSzwaRAVpAdNn",
|
| 232 |
+
"license": "cc-by-4.0",
|
| 233 |
+
"author": "Scenario",
|
| 234 |
+
"title": "scenario:asset_jXUrm3QeKHsQSzwaRAVpAdNn",
|
| 235 |
+
"source_model": "model_rodin-hyper3d",
|
| 236 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 237 |
+
"object_id": "scenario-28ce44f5fbb0c0e011cd",
|
| 238 |
+
"source_object_id": "scenario-28ce44f5fbb0c0e011cd"
|
| 239 |
+
},
|
| 240 |
+
{
|
| 241 |
+
"repo": "scenario-labs/3d-collection",
|
| 242 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 243 |
+
"path": "assets/scenario_asset_2Ro5Mui16ixub1zqw2BiqKaR/output.glb",
|
| 244 |
+
"sha256": "6318af422fbbf062c37484418e866c8fd459df2b98e1bb1e25d933425d60d5ef",
|
| 245 |
+
"asset_id": "scenario:asset_2Ro5Mui16ixub1zqw2BiqKaR",
|
| 246 |
+
"license": "cc-by-4.0",
|
| 247 |
+
"author": "Scenario",
|
| 248 |
+
"title": "scenario:asset_2Ro5Mui16ixub1zqw2BiqKaR",
|
| 249 |
+
"source_model": "model_trellis",
|
| 250 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 251 |
+
"object_id": "scenario-4a5266cce3f49719090d",
|
| 252 |
+
"source_object_id": "scenario-4a5266cce3f49719090d"
|
| 253 |
+
},
|
| 254 |
+
{
|
| 255 |
+
"repo": "scenario-labs/3d-collection",
|
| 256 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 257 |
+
"path": "assets/scenario_asset_BRRWVciFtq3RwW3iv11W6DvT/output.glb",
|
| 258 |
+
"sha256": "ef8fc714c4404fb9390fa8c61074b1b1fe7ed469da4712c5b66bacb46c559133",
|
| 259 |
+
"asset_id": "scenario:asset_BRRWVciFtq3RwW3iv11W6DvT",
|
| 260 |
+
"license": "cc-by-4.0",
|
| 261 |
+
"author": "Scenario",
|
| 262 |
+
"title": "scenario:asset_BRRWVciFtq3RwW3iv11W6DvT",
|
| 263 |
+
"source_model": "model_tripo-p2-multiview-to-3d",
|
| 264 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 265 |
+
"object_id": "scenario-c0a3cbf459276cc685ae",
|
| 266 |
+
"source_object_id": "scenario-c0a3cbf459276cc685ae"
|
| 267 |
+
},
|
| 268 |
+
{
|
| 269 |
+
"repo": "scenario-labs/3d-collection",
|
| 270 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 271 |
+
"path": "assets/scenario_asset_eDVxQybk45x7XjuFeTXKSScc/output.glb",
|
| 272 |
+
"sha256": "00ef0a0908ec20bec84e35b1b0865d5e14a877122525cda1693351cb22ae0c62",
|
| 273 |
+
"asset_id": "scenario:asset_eDVxQybk45x7XjuFeTXKSScc",
|
| 274 |
+
"license": "cc-by-4.0",
|
| 275 |
+
"author": "Scenario",
|
| 276 |
+
"title": "scenario:asset_eDVxQybk45x7XjuFeTXKSScc",
|
| 277 |
+
"source_model": "model_pixal3d",
|
| 278 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 279 |
+
"object_id": "scenario-fc68b47a345c9d6e4963",
|
| 280 |
+
"source_object_id": "scenario-fc68b47a345c9d6e4963"
|
| 281 |
+
},
|
| 282 |
+
{
|
| 283 |
+
"repo": "scenario-labs/3d-collection",
|
| 284 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 285 |
+
"path": "assets/scenario_asset_6ZWKZ6Rzri1Vxy8cSUq2cZTs/output.glb",
|
| 286 |
+
"sha256": "fec06cf24094a4f99ef6e5bae69db44c9d681c97479b68476f4fb741ddb76a9c",
|
| 287 |
+
"asset_id": "scenario:asset_6ZWKZ6Rzri1Vxy8cSUq2cZTs",
|
| 288 |
+
"license": "cc-by-4.0",
|
| 289 |
+
"author": "Scenario",
|
| 290 |
+
"title": "scenario:asset_6ZWKZ6Rzri1Vxy8cSUq2cZTs",
|
| 291 |
+
"source_model": "model_pixal3d",
|
| 292 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 293 |
+
"object_id": "scenario-085e1963fcccdc9d5b3f",
|
| 294 |
+
"source_object_id": "scenario-085e1963fcccdc9d5b3f"
|
| 295 |
+
},
|
| 296 |
+
{
|
| 297 |
+
"repo": "scenario-labs/3d-collection",
|
| 298 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 299 |
+
"path": "assets/scenario_asset_bxgKgzWypCUMwx3uoum89c8f/output.glb",
|
| 300 |
+
"sha256": "08fd1ab1a1d9f5d96ff96c590d15233183a0628ee0c7da7cbc0f94c30934f7aa",
|
| 301 |
+
"asset_id": "scenario:asset_bxgKgzWypCUMwx3uoum89c8f",
|
| 302 |
+
"license": "cc-by-4.0",
|
| 303 |
+
"author": "Scenario",
|
| 304 |
+
"title": "scenario:asset_bxgKgzWypCUMwx3uoum89c8f",
|
| 305 |
+
"source_model": "model_tripo-p2-image-to-3d",
|
| 306 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 307 |
+
"object_id": "scenario-957a1644ed775a4ba828",
|
| 308 |
+
"source_object_id": "scenario-957a1644ed775a4ba828"
|
| 309 |
+
},
|
| 310 |
+
{
|
| 311 |
+
"repo": "scenario-labs/3d-collection",
|
| 312 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 313 |
+
"path": "assets/scenario_asset_SHLHdYJU8ZZcD1RLBoZRN4Dh/output.glb",
|
| 314 |
+
"sha256": "ce0f34aa1819c54a82b5994217c78017502e0cb8da977904bf7a7eaa98aaa01b",
|
| 315 |
+
"asset_id": "scenario:asset_SHLHdYJU8ZZcD1RLBoZRN4Dh",
|
| 316 |
+
"license": "cc-by-4.0",
|
| 317 |
+
"author": "Scenario",
|
| 318 |
+
"title": "scenario:asset_SHLHdYJU8ZZcD1RLBoZRN4Dh",
|
| 319 |
+
"source_model": "model_direct3d-s2",
|
| 320 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 321 |
+
"object_id": "scenario-bac8263386b13cb2ba13",
|
| 322 |
+
"source_object_id": "scenario-bac8263386b13cb2ba13"
|
| 323 |
+
},
|
| 324 |
+
{
|
| 325 |
+
"repo": "scenario-labs/3d-collection",
|
| 326 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 327 |
+
"path": "assets/e8aa5080a9e1176b/61031a4d47639ab5.glb",
|
| 328 |
+
"sha256": "d4119d2b44452f2014d27b3013519eb609eb2355911ad5fe340de258fa8adc84",
|
| 329 |
+
"asset_id": "e8aa5080a9e1176b",
|
| 330 |
+
"license": "cc-by-4.0",
|
| 331 |
+
"author": "Scenario",
|
| 332 |
+
"title": "e8aa5080a9e1176b",
|
| 333 |
+
"source_model": "gpt-6-astra",
|
| 334 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 335 |
+
"object_id": "scenario-5159f9b4437c7798221b",
|
| 336 |
+
"source_object_id": "scenario-5159f9b4437c7798221b"
|
| 337 |
+
},
|
| 338 |
+
{
|
| 339 |
+
"repo": "scenario-labs/3d-collection",
|
| 340 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 341 |
+
"path": "assets/scenario_asset_kFom3by1MoaqECxbVDNLhjm9/output.glb",
|
| 342 |
+
"sha256": "eb02e67db9d6e0787b0600415d7ee00f045834596f24ec741cb0133c659a67a6",
|
| 343 |
+
"asset_id": "scenario:asset_kFom3by1MoaqECxbVDNLhjm9",
|
| 344 |
+
"license": "cc-by-4.0",
|
| 345 |
+
"author": "Scenario",
|
| 346 |
+
"title": "scenario:asset_kFom3by1MoaqECxbVDNLhjm9",
|
| 347 |
+
"source_model": "model_meta-sam-3d-body",
|
| 348 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 349 |
+
"object_id": "scenario-747f6b9cd38dbcf69503",
|
| 350 |
+
"source_object_id": "scenario-747f6b9cd38dbcf69503"
|
| 351 |
+
},
|
| 352 |
+
{
|
| 353 |
+
"repo": "scenario-labs/3d-collection",
|
| 354 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 355 |
+
"path": "assets/scenario_asset_rc9vDsejZEnGMXSBSssE8idQ/output.glb",
|
| 356 |
+
"sha256": "be499e4f5f18ade7908834c95dc221c8dc2224a26e96a2da9ec29553c724873a",
|
| 357 |
+
"asset_id": "scenario:asset_rc9vDsejZEnGMXSBSssE8idQ",
|
| 358 |
+
"license": "cc-by-4.0",
|
| 359 |
+
"author": "Scenario",
|
| 360 |
+
"title": "scenario:asset_rc9vDsejZEnGMXSBSssE8idQ",
|
| 361 |
+
"source_model": "model_rodin-hyper3d",
|
| 362 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 363 |
+
"object_id": "scenario-5b991601f627db98fbf1",
|
| 364 |
+
"source_object_id": "scenario-5b991601f627db98fbf1"
|
| 365 |
+
},
|
| 366 |
+
{
|
| 367 |
+
"repo": "scenario-labs/3d-collection",
|
| 368 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 369 |
+
"path": "assets/scenario_asset_ZMCWJUkPNZ3q2DMUnCZCELoZ/output.glb",
|
| 370 |
+
"sha256": "e8eeec0085132206599009152b4eda705eeea6810e8767270c515be18d4296d5",
|
| 371 |
+
"asset_id": "scenario:asset_ZMCWJUkPNZ3q2DMUnCZCELoZ",
|
| 372 |
+
"license": "cc-by-4.0",
|
| 373 |
+
"author": "Scenario",
|
| 374 |
+
"title": "scenario:asset_ZMCWJUkPNZ3q2DMUnCZCELoZ",
|
| 375 |
+
"source_model": "model_csm-multiview-to-3d",
|
| 376 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 377 |
+
"object_id": "scenario-54f1fab77a40c2cf9628",
|
| 378 |
+
"source_object_id": "scenario-54f1fab77a40c2cf9628"
|
| 379 |
+
},
|
| 380 |
+
{
|
| 381 |
+
"repo": "scenario-labs/3d-collection",
|
| 382 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 383 |
+
"path": "assets/scenario_asset_hBi4aoD5QT99pZuVv5YRwzjn/output.glb",
|
| 384 |
+
"sha256": "fb9dbc5a294d47809a60bacf2672df5f3ffeb465a99eb544ddf63211cd310b91",
|
| 385 |
+
"asset_id": "scenario:asset_hBi4aoD5QT99pZuVv5YRwzjn",
|
| 386 |
+
"license": "cc-by-4.0",
|
| 387 |
+
"author": "Scenario",
|
| 388 |
+
"title": "scenario:asset_hBi4aoD5QT99pZuVv5YRwzjn",
|
| 389 |
+
"source_model": "model_meshy-smart-topology",
|
| 390 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 391 |
+
"object_id": "scenario-281ba76c64b84df68cb5",
|
| 392 |
+
"source_object_id": "scenario-281ba76c64b84df68cb5"
|
| 393 |
+
},
|
| 394 |
+
{
|
| 395 |
+
"repo": "scenario-labs/3d-collection",
|
| 396 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 397 |
+
"path": "assets/scenario_asset_FYB55Mi6cHwTMsdLv4WgKBhe/output.glb",
|
| 398 |
+
"sha256": "b1b16b0410aa55cf84b4f4d68265de10b4a8f28bcfa1f43d16e8faaa1d9072ae",
|
| 399 |
+
"asset_id": "scenario:asset_FYB55Mi6cHwTMsdLv4WgKBhe",
|
| 400 |
+
"license": "cc-by-4.0",
|
| 401 |
+
"author": "Scenario",
|
| 402 |
+
"title": "scenario:asset_FYB55Mi6cHwTMsdLv4WgKBhe",
|
| 403 |
+
"source_model": "model_direct3d-s2",
|
| 404 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 405 |
+
"object_id": "scenario-1fe51bab97a9f112d73a",
|
| 406 |
+
"source_object_id": "scenario-1fe51bab97a9f112d73a"
|
| 407 |
+
},
|
| 408 |
+
{
|
| 409 |
+
"repo": "scenario-labs/3d-collection",
|
| 410 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 411 |
+
"path": "assets/scenario_asset_dD4bnfT5Uk2mdeeCf7tJjeF3/output.glb",
|
| 412 |
+
"sha256": "fbd3c54488095c88be9585aa31a4f12651ff93722d56d210b56f62f51e796179",
|
| 413 |
+
"asset_id": "scenario:asset_dD4bnfT5Uk2mdeeCf7tJjeF3",
|
| 414 |
+
"license": "cc-by-4.0",
|
| 415 |
+
"author": "Scenario",
|
| 416 |
+
"title": "scenario:asset_dD4bnfT5Uk2mdeeCf7tJjeF3",
|
| 417 |
+
"source_model": "model_yvo3d-image-to-3d",
|
| 418 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 419 |
+
"object_id": "scenario-8a1bf58a7e151b7669d4",
|
| 420 |
+
"source_object_id": "scenario-8a1bf58a7e151b7669d4"
|
| 421 |
+
},
|
| 422 |
+
{
|
| 423 |
+
"repo": "scenario-labs/3d-collection",
|
| 424 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 425 |
+
"path": "assets/235d9bb960353a38/056f751264889193.glb",
|
| 426 |
+
"sha256": "b2e4672cd74e52046e7fc96eaf04efcdff2c45676548aeb8602a56edc55e41f4",
|
| 427 |
+
"asset_id": "235d9bb960353a38",
|
| 428 |
+
"license": "cc-by-4.0",
|
| 429 |
+
"author": "Scenario",
|
| 430 |
+
"title": "235d9bb960353a38",
|
| 431 |
+
"source_model": "gpt-6-astra",
|
| 432 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 433 |
+
"object_id": "scenario-387c8e1e591b785054e6",
|
| 434 |
+
"source_object_id": "scenario-387c8e1e591b785054e6"
|
| 435 |
+
},
|
| 436 |
+
{
|
| 437 |
+
"repo": "scenario-labs/3d-collection",
|
| 438 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 439 |
+
"path": "assets/scenario_asset_nKd9y67AGcwgNu93YFAWtuKC/output.glb",
|
| 440 |
+
"sha256": "5a2d35f584bf626d96dc7aa427970b06d9d856d3ecf919707d374dd02670ea69",
|
| 441 |
+
"asset_id": "scenario:asset_nKd9y67AGcwgNu93YFAWtuKC",
|
| 442 |
+
"license": "cc-by-4.0",
|
| 443 |
+
"author": "Scenario",
|
| 444 |
+
"title": "scenario:asset_nKd9y67AGcwgNu93YFAWtuKC",
|
| 445 |
+
"source_model": "model_meshy-img23d",
|
| 446 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 447 |
+
"object_id": "scenario-e88dc70a195271498d23",
|
| 448 |
+
"source_object_id": "scenario-e88dc70a195271498d23"
|
| 449 |
+
},
|
| 450 |
+
{
|
| 451 |
+
"repo": "scenario-labs/3d-collection",
|
| 452 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 453 |
+
"path": "assets/scenario_asset_TmBXvPuDDd6hQohRKc2xA7CD/output.glb",
|
| 454 |
+
"sha256": "040613d474db9d2ac51dfe9cf5cae6f0add07fd2cd9a162a8a257ef2c1216a2d",
|
| 455 |
+
"asset_id": "scenario:asset_TmBXvPuDDd6hQohRKc2xA7CD",
|
| 456 |
+
"license": "cc-by-4.0",
|
| 457 |
+
"author": "Scenario",
|
| 458 |
+
"title": "scenario:asset_TmBXvPuDDd6hQohRKc2xA7CD",
|
| 459 |
+
"source_model": "model_tripo-p1-image-to-3d",
|
| 460 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 461 |
+
"object_id": "scenario-7f98b44563b6a2b1e0a3",
|
| 462 |
+
"source_object_id": "scenario-7f98b44563b6a2b1e0a3"
|
| 463 |
+
},
|
| 464 |
+
{
|
| 465 |
+
"repo": "scenario-labs/3d-collection",
|
| 466 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 467 |
+
"path": "assets/c908eeca2605ca5a/d646af767b201652.glb",
|
| 468 |
+
"sha256": "400c5e6d8cc1e37a7e23bce93cdb3da57f621a6a7e51f7e4c8f4c875ec53e4bd",
|
| 469 |
+
"asset_id": "c908eeca2605ca5a",
|
| 470 |
+
"license": "cc-by-4.0",
|
| 471 |
+
"author": "Scenario",
|
| 472 |
+
"title": "c908eeca2605ca5a",
|
| 473 |
+
"source_model": "claude-opus-5-5",
|
| 474 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 475 |
+
"object_id": "scenario-9f90af50ddf3cc3b8dc9",
|
| 476 |
+
"source_object_id": "scenario-9f90af50ddf3cc3b8dc9"
|
| 477 |
+
},
|
| 478 |
+
{
|
| 479 |
+
"repo": "scenario-labs/3d-collection",
|
| 480 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 481 |
+
"path": "assets/scenario_asset_VdvKmv8rbL34DQdbFQGRCTWQ/output.glb",
|
| 482 |
+
"sha256": "27108c11ba8cc8453c38a835af0c83c3cfef0a7d5e1bdebc8e537bf6be9eb0f0",
|
| 483 |
+
"asset_id": "scenario:asset_VdvKmv8rbL34DQdbFQGRCTWQ",
|
| 484 |
+
"license": "cc-by-4.0",
|
| 485 |
+
"author": "Scenario",
|
| 486 |
+
"title": "scenario:asset_VdvKmv8rbL34DQdbFQGRCTWQ",
|
| 487 |
+
"source_model": "model_trellis",
|
| 488 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 489 |
+
"object_id": "scenario-8e087edc87eb198f7358",
|
| 490 |
+
"source_object_id": "scenario-8e087edc87eb198f7358"
|
| 491 |
+
},
|
| 492 |
+
{
|
| 493 |
+
"repo": "scenario-labs/3d-collection",
|
| 494 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 495 |
+
"path": "assets/scenario_asset_nqVfuhFbnZ6zRdqoJLrRAY4s/output.glb",
|
| 496 |
+
"sha256": "20c2803ec33018117126ac9dfb7f79443c87aa52aacb1890c33f5e548ae044c7",
|
| 497 |
+
"asset_id": "scenario:asset_nqVfuhFbnZ6zRdqoJLrRAY4s",
|
| 498 |
+
"license": "cc-by-4.0",
|
| 499 |
+
"author": "Scenario",
|
| 500 |
+
"title": "scenario:asset_nqVfuhFbnZ6zRdqoJLrRAY4s",
|
| 501 |
+
"source_model": "model_tripo-v2-5-image-to-3d",
|
| 502 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 503 |
+
"object_id": "scenario-c4c39624a27e365901c5",
|
| 504 |
+
"source_object_id": "scenario-c4c39624a27e365901c5"
|
| 505 |
+
},
|
| 506 |
+
{
|
| 507 |
+
"repo": "scenario-labs/3d-collection",
|
| 508 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 509 |
+
"path": "assets/scenario_asset_95NZSL5PxdZjEMQL4QpoWaz7/output.glb",
|
| 510 |
+
"sha256": "64dbc21511a56e9ea3079608348ea56be17b6a62599e93d0a66a13207247ca02",
|
| 511 |
+
"asset_id": "scenario:asset_95NZSL5PxdZjEMQL4QpoWaz7",
|
| 512 |
+
"license": "cc-by-4.0",
|
| 513 |
+
"author": "Scenario",
|
| 514 |
+
"title": "scenario:asset_95NZSL5PxdZjEMQL4QpoWaz7",
|
| 515 |
+
"source_model": "model_pixal3d",
|
| 516 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 517 |
+
"object_id": "scenario-b490750daeb4998c0d16",
|
| 518 |
+
"source_object_id": "scenario-b490750daeb4998c0d16"
|
| 519 |
+
},
|
| 520 |
+
{
|
| 521 |
+
"repo": "scenario-labs/3d-collection",
|
| 522 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 523 |
+
"path": "assets/ad02587cc65da156/f07ca6f5eea265f5.glb",
|
| 524 |
+
"sha256": "7946af4eef28801c74f11cda843b63d4b68164f7288638346302c4877639c2a6",
|
| 525 |
+
"asset_id": "ad02587cc65da156",
|
| 526 |
+
"license": "cc-by-4.0",
|
| 527 |
+
"author": "Scenario",
|
| 528 |
+
"title": "ad02587cc65da156",
|
| 529 |
+
"source_model": "gpt-6-astra",
|
| 530 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 531 |
+
"object_id": "scenario-b1799ce46eb1de635b7e",
|
| 532 |
+
"source_object_id": "scenario-b1799ce46eb1de635b7e"
|
| 533 |
+
},
|
| 534 |
+
{
|
| 535 |
+
"repo": "scenario-labs/3d-collection",
|
| 536 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 537 |
+
"path": "assets/scenario_asset_UDpDkhXVXMnWn3HrU2Ce7fVq/output.glb",
|
| 538 |
+
"sha256": "fb13692795060bf3ed8b95ea121be28266d6de184d4997269d8ad67b54189ccd",
|
| 539 |
+
"asset_id": "scenario:asset_UDpDkhXVXMnWn3HrU2Ce7fVq",
|
| 540 |
+
"license": "cc-by-4.0",
|
| 541 |
+
"author": "Scenario",
|
| 542 |
+
"title": "scenario:asset_UDpDkhXVXMnWn3HrU2Ce7fVq",
|
| 543 |
+
"source_model": "model_meshy-7-img23d",
|
| 544 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 545 |
+
"object_id": "scenario-e602d47f161992c903e0",
|
| 546 |
+
"source_object_id": "scenario-e602d47f161992c903e0"
|
| 547 |
+
},
|
| 548 |
+
{
|
| 549 |
+
"repo": "scenario-labs/3d-collection",
|
| 550 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 551 |
+
"path": "assets/scenario_asset_TYoJxpMFMogTsnBocoU4ne6K/output.glb",
|
| 552 |
+
"sha256": "53c22d8d14999c69660023d7770abc4416181c5ad7b066d584e44172c5f1bbae",
|
| 553 |
+
"asset_id": "scenario:asset_TYoJxpMFMogTsnBocoU4ne6K",
|
| 554 |
+
"license": "cc-by-4.0",
|
| 555 |
+
"author": "Scenario",
|
| 556 |
+
"title": "scenario:asset_TYoJxpMFMogTsnBocoU4ne6K",
|
| 557 |
+
"source_model": "model_rodin-hyper3d",
|
| 558 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 559 |
+
"object_id": "scenario-41224d499165d1141c8a",
|
| 560 |
+
"source_object_id": "scenario-41224d499165d1141c8a"
|
| 561 |
+
},
|
| 562 |
+
{
|
| 563 |
+
"repo": "scenario-labs/3d-collection",
|
| 564 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 565 |
+
"path": "assets/scenario_asset_iRyoVbKAE1hwoq7rmZXxm9Rc/output.glb",
|
| 566 |
+
"sha256": "bacf1d43989eb16af64f1ab47b60d5eeaf951daf7cf7ba3350d8fa69b424f8c2",
|
| 567 |
+
"asset_id": "scenario:asset_iRyoVbKAE1hwoq7rmZXxm9Rc",
|
| 568 |
+
"license": "cc-by-4.0",
|
| 569 |
+
"author": "Scenario",
|
| 570 |
+
"title": "scenario:asset_iRyoVbKAE1hwoq7rmZXxm9Rc",
|
| 571 |
+
"source_model": "model_reconviagen-0-5",
|
| 572 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 573 |
+
"object_id": "scenario-464c65411e1df43484b6",
|
| 574 |
+
"source_object_id": "scenario-464c65411e1df43484b6"
|
| 575 |
+
},
|
| 576 |
+
{
|
| 577 |
+
"repo": "scenario-labs/3d-collection",
|
| 578 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 579 |
+
"path": "assets/scenario_asset_vP1MjicPiq34ia4KFb2U9wXJ/output.glb",
|
| 580 |
+
"sha256": "0946534bdc34a44802500aa58dd509679bc1742ea27770807b0b84e524e221fd",
|
| 581 |
+
"asset_id": "scenario:asset_vP1MjicPiq34ia4KFb2U9wXJ",
|
| 582 |
+
"license": "cc-by-4.0",
|
| 583 |
+
"author": "Scenario",
|
| 584 |
+
"title": "scenario:asset_vP1MjicPiq34ia4KFb2U9wXJ",
|
| 585 |
+
"source_model": "model_tripo-v3-1-image-to-3d",
|
| 586 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 587 |
+
"object_id": "scenario-7f98b44563b6a2b1e0a3",
|
| 588 |
+
"source_object_id": "scenario-7f98b44563b6a2b1e0a3"
|
| 589 |
+
},
|
| 590 |
+
{
|
| 591 |
+
"repo": "scenario-labs/3d-collection",
|
| 592 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 593 |
+
"path": "assets/scenario_asset_QiggxN9z1LL9vXvCsWe5cbfJ/output.glb",
|
| 594 |
+
"sha256": "8861690497c5460bb5d70a0f7af65921673f86d3c82d6d30580d911bc928c74d",
|
| 595 |
+
"asset_id": "scenario:asset_QiggxN9z1LL9vXvCsWe5cbfJ",
|
| 596 |
+
"license": "cc-by-4.0",
|
| 597 |
+
"author": "Scenario",
|
| 598 |
+
"title": "scenario:asset_QiggxN9z1LL9vXvCsWe5cbfJ",
|
| 599 |
+
"source_model": "model_rodin-hyper3d",
|
| 600 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 601 |
+
"object_id": "scenario-556b7a1414e71aade568",
|
| 602 |
+
"source_object_id": "scenario-556b7a1414e71aade568"
|
| 603 |
+
},
|
| 604 |
+
{
|
| 605 |
+
"repo": "scenario-labs/3d-collection",
|
| 606 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 607 |
+
"path": "assets/scenario_asset_VKKCk5EX1kBuk9FwTGzQsd8w/output.glb",
|
| 608 |
+
"sha256": "534f66fdc4ca2cf4129aaa73d0a29618e12e71e693120014f6127f9eaa1c0224",
|
| 609 |
+
"asset_id": "scenario:asset_VKKCk5EX1kBuk9FwTGzQsd8w",
|
| 610 |
+
"license": "cc-by-4.0",
|
| 611 |
+
"author": "Scenario",
|
| 612 |
+
"title": "scenario:asset_VKKCk5EX1kBuk9FwTGzQsd8w",
|
| 613 |
+
"source_model": "model_meshy-smart-topology",
|
| 614 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 615 |
+
"object_id": "scenario-de5c3a8b834fa12da88c",
|
| 616 |
+
"source_object_id": "scenario-de5c3a8b834fa12da88c"
|
| 617 |
+
},
|
| 618 |
+
{
|
| 619 |
+
"repo": "scenario-labs/3d-collection",
|
| 620 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 621 |
+
"path": "assets/scenario_asset_HLWZjA2B6KKDGpYGaXLvmYHq/output.glb",
|
| 622 |
+
"sha256": "037ef71f93039723386cb4f948f9bf4f429e74c7ece6788f51d231caded0811e",
|
| 623 |
+
"asset_id": "scenario:asset_HLWZjA2B6KKDGpYGaXLvmYHq",
|
| 624 |
+
"license": "cc-by-4.0",
|
| 625 |
+
"author": "Scenario",
|
| 626 |
+
"title": "scenario:asset_HLWZjA2B6KKDGpYGaXLvmYHq",
|
| 627 |
+
"source_model": "model_trellis",
|
| 628 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 629 |
+
"object_id": "scenario-53e1e59a0ec494d5c59a",
|
| 630 |
+
"source_object_id": "scenario-53e1e59a0ec494d5c59a"
|
| 631 |
+
},
|
| 632 |
+
{
|
| 633 |
+
"repo": "scenario-labs/3d-collection",
|
| 634 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 635 |
+
"path": "assets/scenario_asset_oLL5ToAk9mAH3dVwfBfButdP/output.glb",
|
| 636 |
+
"sha256": "188bc3a4455a767baaafc73bcdae8a6a1ccdfa0fff5a0cc91b77dfb99601b9dc",
|
| 637 |
+
"asset_id": "scenario:asset_oLL5ToAk9mAH3dVwfBfButdP",
|
| 638 |
+
"license": "cc-by-4.0",
|
| 639 |
+
"author": "Scenario",
|
| 640 |
+
"title": "scenario:asset_oLL5ToAk9mAH3dVwfBfButdP",
|
| 641 |
+
"source_model": "model_meshy-smart-topology",
|
| 642 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 643 |
+
"object_id": "scenario-70507811046725a3d969",
|
| 644 |
+
"source_object_id": "scenario-70507811046725a3d969"
|
| 645 |
+
},
|
| 646 |
+
{
|
| 647 |
+
"repo": "scenario-labs/3d-collection",
|
| 648 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 649 |
+
"path": "assets/scenario_asset_KYwfc9pAw1JEVFaBHSTb194Z/output.glb",
|
| 650 |
+
"sha256": "81ce08dca927c9ee473e09f57fd8388f4213bafaf9f32247b08a080a72651f04",
|
| 651 |
+
"asset_id": "scenario:asset_KYwfc9pAw1JEVFaBHSTb194Z",
|
| 652 |
+
"license": "cc-by-4.0",
|
| 653 |
+
"author": "Scenario",
|
| 654 |
+
"title": "scenario:asset_KYwfc9pAw1JEVFaBHSTb194Z",
|
| 655 |
+
"source_model": "model_yvo3d-image-to-3d",
|
| 656 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 657 |
+
"object_id": "scenario-d6f9d904d7bfb3c27844",
|
| 658 |
+
"source_object_id": "scenario-d6f9d904d7bfb3c27844"
|
| 659 |
+
},
|
| 660 |
+
{
|
| 661 |
+
"repo": "scenario-labs/3d-collection",
|
| 662 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 663 |
+
"path": "assets/scenario_asset_ji6pZ3cCx1yx6AoL2UUzMRwn/output.glb",
|
| 664 |
+
"sha256": "9d8b9a2928de97a17c4e1c1a456e03cdd950df31d32c5217009f44b0e998f55a",
|
| 665 |
+
"asset_id": "scenario:asset_ji6pZ3cCx1yx6AoL2UUzMRwn",
|
| 666 |
+
"license": "cc-by-4.0",
|
| 667 |
+
"author": "Scenario",
|
| 668 |
+
"title": "scenario:asset_ji6pZ3cCx1yx6AoL2UUzMRwn",
|
| 669 |
+
"source_model": "model_tripo-p1-image-to-3d",
|
| 670 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 671 |
+
"object_id": "scenario-085e1963fcccdc9d5b3f",
|
| 672 |
+
"source_object_id": "scenario-085e1963fcccdc9d5b3f"
|
| 673 |
+
},
|
| 674 |
+
{
|
| 675 |
+
"repo": "scenario-labs/3d-collection",
|
| 676 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 677 |
+
"path": "assets/4f43cf75a8660b1c/187a1d9ef36591e9.glb",
|
| 678 |
+
"sha256": "94dad0e2be58d23bb9282f84bed8f753d779f7ca6d6b7cd442ab6e3d25d46778",
|
| 679 |
+
"asset_id": "4f43cf75a8660b1c",
|
| 680 |
+
"license": "cc-by-4.0",
|
| 681 |
+
"author": "Scenario",
|
| 682 |
+
"title": "4f43cf75a8660b1c",
|
| 683 |
+
"source_model": "claude-opus-5-5",
|
| 684 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 685 |
+
"object_id": "scenario-798f7b2b5e4ec95fba0f",
|
| 686 |
+
"source_object_id": "scenario-798f7b2b5e4ec95fba0f"
|
| 687 |
+
},
|
| 688 |
+
{
|
| 689 |
+
"repo": "scenario-labs/3d-collection",
|
| 690 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 691 |
+
"path": "assets/scenario_asset_S8uTvDr43t5chE48nznNmrAc/output.glb",
|
| 692 |
+
"sha256": "b97c45d970d58ff0b6b707b409a3dafd55fe9c91db878e874d83705a6c74b34f",
|
| 693 |
+
"asset_id": "scenario:asset_S8uTvDr43t5chE48nznNmrAc",
|
| 694 |
+
"license": "cc-by-4.0",
|
| 695 |
+
"author": "Scenario",
|
| 696 |
+
"title": "scenario:asset_S8uTvDr43t5chE48nznNmrAc",
|
| 697 |
+
"source_model": "model_csm-multiview-to-3d",
|
| 698 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 699 |
+
"object_id": "scenario-991595188cc901f110dc",
|
| 700 |
+
"source_object_id": "scenario-991595188cc901f110dc"
|
| 701 |
+
},
|
| 702 |
+
{
|
| 703 |
+
"repo": "scenario-labs/3d-collection",
|
| 704 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 705 |
+
"path": "assets/scenario_asset_6gKbavLEWZCCv1VWDCa8efhu/output.glb",
|
| 706 |
+
"sha256": "e74e06e961cee0a0783153ca415c9f2149208eb79deb2e3dd228fdd45807f501",
|
| 707 |
+
"asset_id": "scenario:asset_6gKbavLEWZCCv1VWDCa8efhu",
|
| 708 |
+
"license": "cc-by-4.0",
|
| 709 |
+
"author": "Scenario",
|
| 710 |
+
"title": "scenario:asset_6gKbavLEWZCCv1VWDCa8efhu",
|
| 711 |
+
"source_model": "model_rodin-hyper3d",
|
| 712 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 713 |
+
"object_id": "scenario-f2efa588b531d1fb9ec3",
|
| 714 |
+
"source_object_id": "scenario-f2efa588b531d1fb9ec3"
|
| 715 |
+
},
|
| 716 |
+
{
|
| 717 |
+
"repo": "scenario-labs/3d-collection",
|
| 718 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 719 |
+
"path": "assets/scenario_asset_VfmiL7nFMC3bvSKTkSa7tFuh/output.glb",
|
| 720 |
+
"sha256": "e67a94a1d0870235f8e6081cf56d2bc70e6d61fd9b367f6388d3ab9fba8a30e3",
|
| 721 |
+
"asset_id": "scenario:asset_VfmiL7nFMC3bvSKTkSa7tFuh",
|
| 722 |
+
"license": "cc-by-4.0",
|
| 723 |
+
"author": "Scenario",
|
| 724 |
+
"title": "scenario:asset_VfmiL7nFMC3bvSKTkSa7tFuh",
|
| 725 |
+
"source_model": "model_direct3d-s2",
|
| 726 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 727 |
+
"object_id": "scenario-3431919e57b5420df888",
|
| 728 |
+
"source_object_id": "scenario-3431919e57b5420df888"
|
| 729 |
+
},
|
| 730 |
+
{
|
| 731 |
+
"repo": "scenario-labs/3d-collection",
|
| 732 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 733 |
+
"path": "assets/scenario_asset_8pyMRPstPsnCVsYAf3kz1VQh/output.glb",
|
| 734 |
+
"sha256": "6cc9d5df11152518f71d497d70fb83a6fc64a9cd5179daa082d6de3ab037517c",
|
| 735 |
+
"asset_id": "scenario:asset_8pyMRPstPsnCVsYAf3kz1VQh",
|
| 736 |
+
"license": "cc-by-4.0",
|
| 737 |
+
"author": "Scenario",
|
| 738 |
+
"title": "scenario:asset_8pyMRPstPsnCVsYAf3kz1VQh",
|
| 739 |
+
"source_model": "model_scenario-claude-opus-5-5-3d",
|
| 740 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 741 |
+
"object_id": "scenario-c4613bfdc2da9e7b12e3",
|
| 742 |
+
"source_object_id": "scenario-c4613bfdc2da9e7b12e3"
|
| 743 |
+
},
|
| 744 |
+
{
|
| 745 |
+
"repo": "scenario-labs/3d-collection",
|
| 746 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 747 |
+
"path": "assets/scenario_asset_CpMtjRFkYf4qJFqWXfYUhkgG/output.glb",
|
| 748 |
+
"sha256": "a0403f578ddc56ffe4822861076589d55bf136395f66fa1294740113ff7c79e6",
|
| 749 |
+
"asset_id": "scenario:asset_CpMtjRFkYf4qJFqWXfYUhkgG",
|
| 750 |
+
"license": "cc-by-4.0",
|
| 751 |
+
"author": "Scenario",
|
| 752 |
+
"title": "scenario:asset_CpMtjRFkYf4qJFqWXfYUhkgG",
|
| 753 |
+
"source_model": "model_yvo3d-image-to-3d",
|
| 754 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 755 |
+
"object_id": "scenario-bf6ef83e0415cbcaef42",
|
| 756 |
+
"source_object_id": "scenario-bf6ef83e0415cbcaef42"
|
| 757 |
+
},
|
| 758 |
+
{
|
| 759 |
+
"repo": "scenario-labs/3d-collection",
|
| 760 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 761 |
+
"path": "assets/scenario_asset_TtQmB4yb5GmPs2XoMhEoTbXt/output.glb",
|
| 762 |
+
"sha256": "6e3ea0ad4208a4f0b55d981218756ab9aabcfd335456b49d66c57989d8ac7932",
|
| 763 |
+
"asset_id": "scenario:asset_TtQmB4yb5GmPs2XoMhEoTbXt",
|
| 764 |
+
"license": "cc-by-4.0",
|
| 765 |
+
"author": "Scenario",
|
| 766 |
+
"title": "scenario:asset_TtQmB4yb5GmPs2XoMhEoTbXt",
|
| 767 |
+
"source_model": "model_trellis",
|
| 768 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 769 |
+
"object_id": "scenario-7230f13fded428b3dd03",
|
| 770 |
+
"source_object_id": "scenario-7230f13fded428b3dd03"
|
| 771 |
+
},
|
| 772 |
+
{
|
| 773 |
+
"repo": "scenario-labs/3d-collection",
|
| 774 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 775 |
+
"path": "assets/scenario_asset_RgnwiEnHczYcZ4jJ9TLc3eE4/output.glb",
|
| 776 |
+
"sha256": "8b8ac09c744ed38bc9f70262021334cfa0c89fe0653c8375fe1ceeb77cc71e21",
|
| 777 |
+
"asset_id": "scenario:asset_RgnwiEnHczYcZ4jJ9TLc3eE4",
|
| 778 |
+
"license": "cc-by-4.0",
|
| 779 |
+
"author": "Scenario",
|
| 780 |
+
"title": "scenario:asset_RgnwiEnHczYcZ4jJ9TLc3eE4",
|
| 781 |
+
"source_model": "model_rodin-hyper3d-v2-5-fast",
|
| 782 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 783 |
+
"object_id": "scenario-4e2e45c882aa9d2e2716",
|
| 784 |
+
"source_object_id": "scenario-4e2e45c882aa9d2e2716"
|
| 785 |
+
},
|
| 786 |
+
{
|
| 787 |
+
"repo": "scenario-labs/3d-collection",
|
| 788 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 789 |
+
"path": "assets/scenario_asset_P2nUBx2nK3xNKJFMBh8P3SbT/output.glb",
|
| 790 |
+
"sha256": "708543146174141e5f95d32283649fd0504394d53c8722bd7a0c39e2bef12a72",
|
| 791 |
+
"asset_id": "scenario:asset_P2nUBx2nK3xNKJFMBh8P3SbT",
|
| 792 |
+
"license": "cc-by-4.0",
|
| 793 |
+
"author": "Scenario",
|
| 794 |
+
"title": "scenario:asset_P2nUBx2nK3xNKJFMBh8P3SbT",
|
| 795 |
+
"source_model": "model_meta-sam-3d-body",
|
| 796 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 797 |
+
"object_id": "scenario-05a748c9c86f615a9506",
|
| 798 |
+
"source_object_id": "scenario-05a748c9c86f615a9506"
|
| 799 |
+
},
|
| 800 |
+
{
|
| 801 |
+
"repo": "scenario-labs/3d-collection",
|
| 802 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 803 |
+
"path": "assets/4d54a50094e52d2b/abe7aea7e42e2cfa.glb",
|
| 804 |
+
"sha256": "24971a53f2651f66e92c2da539675222bed38d2a08a027e135268de7926729f8",
|
| 805 |
+
"asset_id": "4d54a50094e52d2b",
|
| 806 |
+
"license": "cc-by-4.0",
|
| 807 |
+
"author": "Scenario",
|
| 808 |
+
"title": "4d54a50094e52d2b",
|
| 809 |
+
"source_model": "gpt-6-astra",
|
| 810 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 811 |
+
"object_id": "scenario-a0ab890ab088491fcbe7",
|
| 812 |
+
"source_object_id": "scenario-a0ab890ab088491fcbe7"
|
| 813 |
+
},
|
| 814 |
+
{
|
| 815 |
+
"repo": "scenario-labs/3d-collection",
|
| 816 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 817 |
+
"path": "assets/d53af1d69a7df48e/b617bf376be6deca.glb",
|
| 818 |
+
"sha256": "a0f629173fd79615e898d214d91b1007df0b7211ab0d77070b5a32b701e9dbc7",
|
| 819 |
+
"asset_id": "d53af1d69a7df48e",
|
| 820 |
+
"license": "cc-by-4.0",
|
| 821 |
+
"author": "Scenario",
|
| 822 |
+
"title": "d53af1d69a7df48e",
|
| 823 |
+
"source_model": "gpt-6-astra",
|
| 824 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 825 |
+
"object_id": "scenario-65648f8af659f2626c9a",
|
| 826 |
+
"source_object_id": "scenario-65648f8af659f2626c9a"
|
| 827 |
+
},
|
| 828 |
+
{
|
| 829 |
+
"repo": "scenario-labs/3d-collection",
|
| 830 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 831 |
+
"path": "assets/scenario_asset_gA89x3a9cy4cUzVGN3KDA4W9/output.glb",
|
| 832 |
+
"sha256": "fc73c6cf8fb66a90d4ce4e707d876f2bfc0b87bc5cfaaa20215866fab1334ab2",
|
| 833 |
+
"asset_id": "scenario:asset_gA89x3a9cy4cUzVGN3KDA4W9",
|
| 834 |
+
"license": "cc-by-4.0",
|
| 835 |
+
"author": "Scenario",
|
| 836 |
+
"title": "scenario:asset_gA89x3a9cy4cUzVGN3KDA4W9",
|
| 837 |
+
"source_model": "model_yvo3d-image-to-3d",
|
| 838 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 839 |
+
"object_id": "scenario-a1125b61956d2b157da5",
|
| 840 |
+
"source_object_id": "scenario-a1125b61956d2b157da5"
|
| 841 |
+
},
|
| 842 |
+
{
|
| 843 |
+
"repo": "scenario-labs/3d-collection",
|
| 844 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 845 |
+
"path": "assets/scenario_asset_fzZEg2u24taWgTTRTMkY2hiK/output.glb",
|
| 846 |
+
"sha256": "73a20bfd87f97278d20e4fadcbc999dcfe698b7d8d6db89ac0a68c7ca7edf881",
|
| 847 |
+
"asset_id": "scenario:asset_fzZEg2u24taWgTTRTMkY2hiK",
|
| 848 |
+
"license": "cc-by-4.0",
|
| 849 |
+
"author": "Scenario",
|
| 850 |
+
"title": "scenario:asset_fzZEg2u24taWgTTRTMkY2hiK",
|
| 851 |
+
"source_model": "model_rodin-hyper3d-v2-5-fast",
|
| 852 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 853 |
+
"object_id": "scenario-085e1963fcccdc9d5b3f",
|
| 854 |
+
"source_object_id": "scenario-085e1963fcccdc9d5b3f"
|
| 855 |
+
},
|
| 856 |
+
{
|
| 857 |
+
"repo": "allenai/objaverse",
|
| 858 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 859 |
+
"path": "glbs/000-000/04bd8f55740342429cbf34ca9a5b9792.glb",
|
| 860 |
+
"asset_id": "04bd8f55740342429cbf34ca9a5b9792",
|
| 861 |
+
"object_id": "objaverse-04bd8f55740342429cbf34ca9a5b9792",
|
| 862 |
+
"license": "cc0-1.0",
|
| 863 |
+
"author": "Digital Atlas of Ancient Life",
|
| 864 |
+
"title": "Gastropod: Ecphora quadricostata (PRI 70750)",
|
| 865 |
+
"source_url": "https://sketchfab.com/3d-models/04bd8f55740342429cbf34ca9a5b9792",
|
| 866 |
+
"sha256": "fb11df227261356a902fa0f725690902c7297e7eb6b92157f460e3f0b93f9a68",
|
| 867 |
+
"source_object_id": "objaverse-04bd8f55740342429cbf34ca9a5b9792"
|
| 868 |
+
},
|
| 869 |
+
{
|
| 870 |
+
"repo": "allenai/objaverse",
|
| 871 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 872 |
+
"path": "glbs/000-000/1a57a0d6609145b486ed5b1d3e9ec7fb.glb",
|
| 873 |
+
"asset_id": "1a57a0d6609145b486ed5b1d3e9ec7fb",
|
| 874 |
+
"object_id": "objaverse-1a57a0d6609145b486ed5b1d3e9ec7fb",
|
| 875 |
+
"license": "cc0-1.0",
|
| 876 |
+
"author": "Cleveland Museum of Art",
|
| 877 |
+
"title": "1997.11 Standing Bodhisattva",
|
| 878 |
+
"source_url": "https://sketchfab.com/3d-models/1a57a0d6609145b486ed5b1d3e9ec7fb",
|
| 879 |
+
"sha256": "52825f9bc6ab3f301107a766c23efc346157702952b7d929144881d43ae33965",
|
| 880 |
+
"source_object_id": "objaverse-1a57a0d6609145b486ed5b1d3e9ec7fb"
|
| 881 |
+
},
|
| 882 |
+
{
|
| 883 |
+
"repo": "allenai/objaverse",
|
| 884 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 885 |
+
"path": "glbs/000-000/d8c7caeb4497447ba801ed4479575d12.glb",
|
| 886 |
+
"asset_id": "d8c7caeb4497447ba801ed4479575d12",
|
| 887 |
+
"object_id": "objaverse-d8c7caeb4497447ba801ed4479575d12",
|
| 888 |
+
"license": "cc0-1.0",
|
| 889 |
+
"author": "Digital Atlas of Ancient Life",
|
| 890 |
+
"title": "Gastropod: Diodora sp. (PRI 76791)",
|
| 891 |
+
"source_url": "https://sketchfab.com/3d-models/d8c7caeb4497447ba801ed4479575d12",
|
| 892 |
+
"sha256": "26809d92313f7a569a29f8fd1cebb1b0277d866ade5449fd80b515cd2704e9ab",
|
| 893 |
+
"source_object_id": "objaverse-d8c7caeb4497447ba801ed4479575d12"
|
| 894 |
+
},
|
| 895 |
+
{
|
| 896 |
+
"repo": "allenai/objaverse",
|
| 897 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 898 |
+
"path": "glbs/000-000/521be39e2ea94bbaa1f06f3e89b0ad97.glb",
|
| 899 |
+
"asset_id": "521be39e2ea94bbaa1f06f3e89b0ad97",
|
| 900 |
+
"object_id": "objaverse-521be39e2ea94bbaa1f06f3e89b0ad97",
|
| 901 |
+
"license": "cc0-1.0",
|
| 902 |
+
"author": "Virtual Museums of Ma\u0142opolska",
|
| 903 |
+
"title": "Cauldron",
|
| 904 |
+
"source_url": "https://sketchfab.com/3d-models/521be39e2ea94bbaa1f06f3e89b0ad97",
|
| 905 |
+
"sha256": "db9d04dd646f6b162fcd9ed3411b721f042007b468e6e7fd3fb933c1663e5183",
|
| 906 |
+
"source_object_id": "objaverse-521be39e2ea94bbaa1f06f3e89b0ad97"
|
| 907 |
+
},
|
| 908 |
+
{
|
| 909 |
+
"repo": "allenai/objaverse",
|
| 910 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 911 |
+
"path": "glbs/000-001/8a9782ade2764984a792f3fb553e27e5.glb",
|
| 912 |
+
"asset_id": "8a9782ade2764984a792f3fb553e27e5",
|
| 913 |
+
"object_id": "objaverse-8a9782ade2764984a792f3fb553e27e5",
|
| 914 |
+
"license": "cc0-1.0",
|
| 915 |
+
"author": "Virtual Museums of Ma\u0142opolska",
|
| 916 |
+
"title": "Perfume bottle in the case",
|
| 917 |
+
"source_url": "https://sketchfab.com/3d-models/8a9782ade2764984a792f3fb553e27e5",
|
| 918 |
+
"sha256": "6ac1a0928f516698df9e61647546fb77e342a56e15938fadbe3320a8fd605b2e",
|
| 919 |
+
"source_object_id": "objaverse-8a9782ade2764984a792f3fb553e27e5"
|
| 920 |
+
},
|
| 921 |
+
{
|
| 922 |
+
"repo": "allenai/objaverse",
|
| 923 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 924 |
+
"path": "glbs/000-000/d1fe37e659c84bacbbfeb54ab2fbbd6e.glb",
|
| 925 |
+
"asset_id": "d1fe37e659c84bacbbfeb54ab2fbbd6e",
|
| 926 |
+
"object_id": "objaverse-d1fe37e659c84bacbbfeb54ab2fbbd6e",
|
| 927 |
+
"license": "cc0-1.0",
|
| 928 |
+
"author": "Museum f\u00fcr Kunst und Gewerbe Hamburg",
|
| 929 |
+
"title": "Jug",
|
| 930 |
+
"source_url": "https://sketchfab.com/3d-models/d1fe37e659c84bacbbfeb54ab2fbbd6e",
|
| 931 |
+
"sha256": "f04a2890238f3ba40dcf13cd78fc97c376de0cb14cfa46fbc6504866c77fd20c",
|
| 932 |
+
"source_object_id": "objaverse-d1fe37e659c84bacbbfeb54ab2fbbd6e"
|
| 933 |
+
},
|
| 934 |
+
{
|
| 935 |
+
"repo": "allenai/objaverse",
|
| 936 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 937 |
+
"path": "glbs/000-001/5f2b9bd73ce64fbfbc8dc4309d429b1e.glb",
|
| 938 |
+
"asset_id": "5f2b9bd73ce64fbfbc8dc4309d429b1e",
|
| 939 |
+
"object_id": "objaverse-5f2b9bd73ce64fbfbc8dc4309d429b1e",
|
| 940 |
+
"license": "cc0-1.0",
|
| 941 |
+
"author": "Digital Atlas of Ancient Life",
|
| 942 |
+
"title": "Bivalve: Isognomon maxillata (PRI 76763)",
|
| 943 |
+
"source_url": "https://sketchfab.com/3d-models/5f2b9bd73ce64fbfbc8dc4309d429b1e",
|
| 944 |
+
"sha256": "70d31c2792ffc229285630d478ae5d27372f6f8583f33c4e068b76f011ab0ceb",
|
| 945 |
+
"source_object_id": "objaverse-5f2b9bd73ce64fbfbc8dc4309d429b1e"
|
| 946 |
+
},
|
| 947 |
+
{
|
| 948 |
+
"repo": "allenai/objaverse",
|
| 949 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 950 |
+
"path": "glbs/000-001/1b640e4be73d461abd24eee5e1b61301.glb",
|
| 951 |
+
"asset_id": "1b640e4be73d461abd24eee5e1b61301",
|
| 952 |
+
"object_id": "objaverse-1b640e4be73d461abd24eee5e1b61301",
|
| 953 |
+
"license": "cc0-1.0",
|
| 954 |
+
"author": "Virtual Museums of Ma\u0142opolska",
|
| 955 |
+
"title": "Sculpture of man and woman",
|
| 956 |
+
"source_url": "https://sketchfab.com/3d-models/1b640e4be73d461abd24eee5e1b61301",
|
| 957 |
+
"sha256": "d723ed8842843bb49c04f4eecc73a36d48985b991b96a7ec0938f9680bad4727",
|
| 958 |
+
"source_object_id": "objaverse-1b640e4be73d461abd24eee5e1b61301"
|
| 959 |
+
},
|
| 960 |
+
{
|
| 961 |
+
"repo": "allenai/objaverse",
|
| 962 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 963 |
+
"path": "glbs/000-001/250c1384333d484895778e6b951a0fab.glb",
|
| 964 |
+
"asset_id": "250c1384333d484895778e6b951a0fab",
|
| 965 |
+
"object_id": "objaverse-250c1384333d484895778e6b951a0fab",
|
| 966 |
+
"license": "cc0-1.0",
|
| 967 |
+
"author": "Cleveland Museum of Art",
|
| 968 |
+
"title": "1962.153 Bottle with Fish Design",
|
| 969 |
+
"source_url": "https://sketchfab.com/3d-models/250c1384333d484895778e6b951a0fab",
|
| 970 |
+
"sha256": "e34fd4afda321bb3a5a2c6304d7e1dee3b70d17b2b507778a3047d56d870524a",
|
| 971 |
+
"source_object_id": "objaverse-250c1384333d484895778e6b951a0fab"
|
| 972 |
+
},
|
| 973 |
+
{
|
| 974 |
+
"repo": "allenai/objaverse",
|
| 975 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 976 |
+
"path": "glbs/000-001/d433f7d2bc6b4d6eb95497210b3736dd.glb",
|
| 977 |
+
"asset_id": "d433f7d2bc6b4d6eb95497210b3736dd",
|
| 978 |
+
"object_id": "objaverse-d433f7d2bc6b4d6eb95497210b3736dd",
|
| 979 |
+
"license": "cc0-1.0",
|
| 980 |
+
"author": "Virtual Museums of Ma\u0142opolska",
|
| 981 |
+
"title": "Painted Celtic flask",
|
| 982 |
+
"source_url": "https://sketchfab.com/3d-models/d433f7d2bc6b4d6eb95497210b3736dd",
|
| 983 |
+
"sha256": "369ebdff7bfd051a09f518a6b1855e957f74372874e2670cbb889a29d1f5228e",
|
| 984 |
+
"source_object_id": "objaverse-d433f7d2bc6b4d6eb95497210b3736dd"
|
| 985 |
+
},
|
| 986 |
+
{
|
| 987 |
+
"repo": "allenai/objaverse",
|
| 988 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 989 |
+
"path": "glbs/000-001/d488f678a35c4789a75641d2be1773ef.glb",
|
| 990 |
+
"asset_id": "d488f678a35c4789a75641d2be1773ef",
|
| 991 |
+
"object_id": "objaverse-d488f678a35c4789a75641d2be1773ef",
|
| 992 |
+
"license": "cc0-1.0",
|
| 993 |
+
"author": "Digital Atlas of Ancient Life",
|
| 994 |
+
"title": "Amplexopora filiasa (PRI 76723)",
|
| 995 |
+
"source_url": "https://sketchfab.com/3d-models/d488f678a35c4789a75641d2be1773ef",
|
| 996 |
+
"sha256": "11acf56ca828a407370eca48f1decdca2da10e378dfd76c73d6d25def96a2da0",
|
| 997 |
+
"source_object_id": "objaverse-d488f678a35c4789a75641d2be1773ef"
|
| 998 |
+
},
|
| 999 |
+
{
|
| 1000 |
+
"repo": "allenai/objaverse",
|
| 1001 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1002 |
+
"path": "glbs/000-000/93d6432c6d834ffea49af75e93b4f729.glb",
|
| 1003 |
+
"asset_id": "93d6432c6d834ffea49af75e93b4f729",
|
| 1004 |
+
"object_id": "objaverse-93d6432c6d834ffea49af75e93b4f729",
|
| 1005 |
+
"license": "cc0-1.0",
|
| 1006 |
+
"author": "Digital Atlas of Ancient Life",
|
| 1007 |
+
"title": "PRI Sideratrea Siderea",
|
| 1008 |
+
"source_url": "https://sketchfab.com/3d-models/93d6432c6d834ffea49af75e93b4f729",
|
| 1009 |
+
"sha256": "509e123e5a6e969bb9ffee1e5c781ed2c2bd9347ca67d58264ca4e1ac0950ea5",
|
| 1010 |
+
"source_object_id": "objaverse-93d6432c6d834ffea49af75e93b4f729"
|
| 1011 |
+
},
|
| 1012 |
+
{
|
| 1013 |
+
"repo": "allenai/objaverse",
|
| 1014 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1015 |
+
"path": "glbs/000-000/30256f207c5e4500befb371273ab6878.glb",
|
| 1016 |
+
"asset_id": "30256f207c5e4500befb371273ab6878",
|
| 1017 |
+
"object_id": "objaverse-30256f207c5e4500befb371273ab6878",
|
| 1018 |
+
"license": "cc0-1.0",
|
| 1019 |
+
"author": "cineg",
|
| 1020 |
+
"title": "Candle Holder",
|
| 1021 |
+
"source_url": "https://sketchfab.com/3d-models/30256f207c5e4500befb371273ab6878",
|
| 1022 |
+
"sha256": "888e65cb92495736abdc3c425302afa7ce11131d23b54921725ab18b94115c6d",
|
| 1023 |
+
"source_object_id": "objaverse-30256f207c5e4500befb371273ab6878"
|
| 1024 |
+
},
|
| 1025 |
+
{
|
| 1026 |
+
"repo": "allenai/objaverse",
|
| 1027 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1028 |
+
"path": "glbs/000-000/71db1c656c1c415f9ba0948e0dba8ba6.glb",
|
| 1029 |
+
"asset_id": "71db1c656c1c415f9ba0948e0dba8ba6",
|
| 1030 |
+
"object_id": "objaverse-71db1c656c1c415f9ba0948e0dba8ba6",
|
| 1031 |
+
"license": "cc0-1.0",
|
| 1032 |
+
"author": "galway3d",
|
| 1033 |
+
"title": "Fox",
|
| 1034 |
+
"source_url": "https://sketchfab.com/3d-models/71db1c656c1c415f9ba0948e0dba8ba6",
|
| 1035 |
+
"sha256": "396d35947c52811e43188b60859cd9231d1669f1993211fd4e5921fc67a40f02",
|
| 1036 |
+
"source_object_id": "objaverse-71db1c656c1c415f9ba0948e0dba8ba6"
|
| 1037 |
+
},
|
| 1038 |
+
{
|
| 1039 |
+
"repo": "allenai/objaverse",
|
| 1040 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1041 |
+
"path": "glbs/000-001/57284863a5c74b3ea2da7dbd26876662.glb",
|
| 1042 |
+
"asset_id": "57284863a5c74b3ea2da7dbd26876662",
|
| 1043 |
+
"object_id": "objaverse-57284863a5c74b3ea2da7dbd26876662",
|
| 1044 |
+
"license": "cc0-1.0",
|
| 1045 |
+
"author": "galway3d",
|
| 1046 |
+
"title": "Toorelectra - Sweathouse",
|
| 1047 |
+
"source_url": "https://sketchfab.com/3d-models/57284863a5c74b3ea2da7dbd26876662",
|
| 1048 |
+
"sha256": "177732d31e10229d647e9f87f6dc1bfb9cdf7592a9ade72a1a51518f7564b83a",
|
| 1049 |
+
"source_object_id": "objaverse-57284863a5c74b3ea2da7dbd26876662"
|
| 1050 |
+
},
|
| 1051 |
+
{
|
| 1052 |
+
"repo": "allenai/objaverse",
|
| 1053 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1054 |
+
"path": "glbs/000-001/5a0ea446a4284839aaad41bfb054f376.glb",
|
| 1055 |
+
"asset_id": "5a0ea446a4284839aaad41bfb054f376",
|
| 1056 |
+
"object_id": "objaverse-5a0ea446a4284839aaad41bfb054f376",
|
| 1057 |
+
"license": "cc0-1.0",
|
| 1058 |
+
"author": "Minneapolis Institute of Art",
|
| 1059 |
+
"title": "Yan steamer, 11th century BCE",
|
| 1060 |
+
"source_url": "https://sketchfab.com/3d-models/5a0ea446a4284839aaad41bfb054f376",
|
| 1061 |
+
"sha256": "45d12874d38a7fe1ef1b4612912ccfabb7541cb8eb0dde961dd057e426ab61ea",
|
| 1062 |
+
"source_object_id": "objaverse-5a0ea446a4284839aaad41bfb054f376"
|
| 1063 |
+
},
|
| 1064 |
+
{
|
| 1065 |
+
"repo": "allenai/objaverse",
|
| 1066 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1067 |
+
"path": "glbs/000-000/9525cde4b189451289432e3f98ffc90d.glb",
|
| 1068 |
+
"asset_id": "9525cde4b189451289432e3f98ffc90d",
|
| 1069 |
+
"object_id": "objaverse-9525cde4b189451289432e3f98ffc90d",
|
| 1070 |
+
"license": "cc0-1.0",
|
| 1071 |
+
"author": "Museo Nacional de Historia Natural de Chile",
|
| 1072 |
+
"title": "Pelagornis chilensis. Rama mandibular derecha",
|
| 1073 |
+
"source_url": "https://sketchfab.com/3d-models/9525cde4b189451289432e3f98ffc90d",
|
| 1074 |
+
"sha256": "92424bd9516d529890b8002610b074f115ce6e9b42fdd582602897115bba7f43",
|
| 1075 |
+
"source_object_id": "objaverse-9525cde4b189451289432e3f98ffc90d"
|
| 1076 |
+
},
|
| 1077 |
+
{
|
| 1078 |
+
"repo": "allenai/objaverse",
|
| 1079 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1080 |
+
"path": "glbs/000-001/f8f81494d773464eb4af4c863a212ab9.glb",
|
| 1081 |
+
"asset_id": "f8f81494d773464eb4af4c863a212ab9",
|
| 1082 |
+
"object_id": "objaverse-f8f81494d773464eb4af4c863a212ab9",
|
| 1083 |
+
"license": "cc0-1.0",
|
| 1084 |
+
"author": "Digital Atlas of Ancient Life",
|
| 1085 |
+
"title": "Ursus spelaeus (cave bear) lower jaw (PRI 50009)",
|
| 1086 |
+
"source_url": "https://sketchfab.com/3d-models/f8f81494d773464eb4af4c863a212ab9",
|
| 1087 |
+
"sha256": "6149bc417c4a33a209655629a9e6aa46f7498166c4b9c44e830e45c4d2a08903",
|
| 1088 |
+
"source_object_id": "objaverse-f8f81494d773464eb4af4c863a212ab9"
|
| 1089 |
+
},
|
| 1090 |
+
{
|
| 1091 |
+
"repo": "allenai/objaverse",
|
| 1092 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1093 |
+
"path": "glbs/000-000/0068a53f561d4dccbaef45841107a42d.glb",
|
| 1094 |
+
"asset_id": "0068a53f561d4dccbaef45841107a42d",
|
| 1095 |
+
"object_id": "objaverse-0068a53f561d4dccbaef45841107a42d",
|
| 1096 |
+
"license": "cc0-1.0",
|
| 1097 |
+
"author": "Museo Nacional de Historia Natural de Chile",
|
| 1098 |
+
"title": "Ericusa sowerbyi 1025",
|
| 1099 |
+
"source_url": "https://sketchfab.com/3d-models/0068a53f561d4dccbaef45841107a42d",
|
| 1100 |
+
"sha256": "f51bc1301f8ef27e139c9f994e5c8257eb0ab8f71613ed46f0878c2e477982da",
|
| 1101 |
+
"source_object_id": "objaverse-0068a53f561d4dccbaef45841107a42d"
|
| 1102 |
+
},
|
| 1103 |
+
{
|
| 1104 |
+
"repo": "allenai/objaverse",
|
| 1105 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1106 |
+
"path": "glbs/000-000/559b7a2ae50f426a8993b609d22931ff.glb",
|
| 1107 |
+
"asset_id": "559b7a2ae50f426a8993b609d22931ff",
|
| 1108 |
+
"object_id": "objaverse-559b7a2ae50f426a8993b609d22931ff",
|
| 1109 |
+
"license": "cc0-1.0",
|
| 1110 |
+
"author": "Digital Atlas of Ancient Life",
|
| 1111 |
+
"title": "Angiosperm: Koelreuteria allenii (Cornell Univ.)",
|
| 1112 |
+
"source_url": "https://sketchfab.com/3d-models/559b7a2ae50f426a8993b609d22931ff",
|
| 1113 |
+
"sha256": "36b7be877bd77ebb5c24b4615cb0b059226a27727867b9ee40be5eb94bcc1bb0",
|
| 1114 |
+
"source_object_id": "objaverse-559b7a2ae50f426a8993b609d22931ff"
|
| 1115 |
+
},
|
| 1116 |
+
{
|
| 1117 |
+
"repo": "allenai/objaverse",
|
| 1118 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1119 |
+
"path": "glbs/000-001/4478d3dd074b40ee96fcbcb227e5a732.glb",
|
| 1120 |
+
"asset_id": "4478d3dd074b40ee96fcbcb227e5a732",
|
| 1121 |
+
"object_id": "objaverse-4478d3dd074b40ee96fcbcb227e5a732",
|
| 1122 |
+
"license": "cc0-1.0",
|
| 1123 |
+
"author": "Virtual Museums of Ma\u0142opolska",
|
| 1124 |
+
"title": "COTY powder packaging",
|
| 1125 |
+
"source_url": "https://sketchfab.com/3d-models/4478d3dd074b40ee96fcbcb227e5a732",
|
| 1126 |
+
"sha256": "eb3723c04cb44b69b7298628308e15161f16b584121c479c8910fc8ea642a95d",
|
| 1127 |
+
"source_object_id": "objaverse-4478d3dd074b40ee96fcbcb227e5a732"
|
| 1128 |
+
},
|
| 1129 |
+
{
|
| 1130 |
+
"repo": "allenai/objaverse",
|
| 1131 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1132 |
+
"path": "glbs/000-001/ddc820bb5e3a422b9693912322e23acc.glb",
|
| 1133 |
+
"asset_id": "ddc820bb5e3a422b9693912322e23acc",
|
| 1134 |
+
"object_id": "objaverse-ddc820bb5e3a422b9693912322e23acc",
|
| 1135 |
+
"license": "cc0-1.0",
|
| 1136 |
+
"author": "Digital Atlas of Ancient Life",
|
| 1137 |
+
"title": "Trilobite: Isotelus sp. (PRI 45502)",
|
| 1138 |
+
"source_url": "https://sketchfab.com/3d-models/ddc820bb5e3a422b9693912322e23acc",
|
| 1139 |
+
"sha256": "767ebeec273e4ac6536d1c96371c304927bac5a364517e2cbbd646bd533227a1",
|
| 1140 |
+
"source_object_id": "objaverse-ddc820bb5e3a422b9693912322e23acc"
|
| 1141 |
+
},
|
| 1142 |
+
{
|
| 1143 |
+
"repo": "allenai/objaverse",
|
| 1144 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1145 |
+
"path": "glbs/000-001/dd354a8ba61446c0a8c98685458ee5a9.glb",
|
| 1146 |
+
"asset_id": "dd354a8ba61446c0a8c98685458ee5a9",
|
| 1147 |
+
"object_id": "objaverse-dd354a8ba61446c0a8c98685458ee5a9",
|
| 1148 |
+
"license": "cc0-1.0",
|
| 1149 |
+
"author": "Digital Atlas of Ancient Life",
|
| 1150 |
+
"title": "Brachiopod: Athyris spiriferoides (PRI 44050)",
|
| 1151 |
+
"source_url": "https://sketchfab.com/3d-models/dd354a8ba61446c0a8c98685458ee5a9",
|
| 1152 |
+
"sha256": "189992257282b2d49fd3aca211fbcc65119c5c87aff4aa95e199fd01091fa146",
|
| 1153 |
+
"source_object_id": "objaverse-dd354a8ba61446c0a8c98685458ee5a9"
|
| 1154 |
+
},
|
| 1155 |
+
{
|
| 1156 |
+
"repo": "allenai/objaverse",
|
| 1157 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1158 |
+
"path": "glbs/000-001/0b7c6e8e32144b72806ed31cb49b4145.glb",
|
| 1159 |
+
"asset_id": "0b7c6e8e32144b72806ed31cb49b4145",
|
| 1160 |
+
"object_id": "objaverse-0b7c6e8e32144b72806ed31cb49b4145",
|
| 1161 |
+
"license": "cc0-1.0",
|
| 1162 |
+
"author": "Digital Atlas of Ancient Life",
|
| 1163 |
+
"title": "Pyrite",
|
| 1164 |
+
"source_url": "https://sketchfab.com/3d-models/0b7c6e8e32144b72806ed31cb49b4145",
|
| 1165 |
+
"sha256": "853f762ce4665b29593b3bf341bbfe28211d44d9b853b55ff84deec894d81ad2",
|
| 1166 |
+
"source_object_id": "objaverse-0b7c6e8e32144b72806ed31cb49b4145"
|
| 1167 |
+
},
|
| 1168 |
+
{
|
| 1169 |
+
"repo": "allenai/objaverse",
|
| 1170 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1171 |
+
"path": "glbs/000-000/1034cd8e4df5430cb874f012415a43b0.glb",
|
| 1172 |
+
"asset_id": "1034cd8e4df5430cb874f012415a43b0",
|
| 1173 |
+
"object_id": "objaverse-1034cd8e4df5430cb874f012415a43b0",
|
| 1174 |
+
"license": "cc0-1.0",
|
| 1175 |
+
"author": "Virtual Museums of Ma\u0142opolska",
|
| 1176 |
+
"title": "Ding censer with an openwork cover",
|
| 1177 |
+
"source_url": "https://sketchfab.com/3d-models/1034cd8e4df5430cb874f012415a43b0",
|
| 1178 |
+
"sha256": "4cdf363f7d84fd44406fc6e5237c5baa5166506a7a58241f22d93e9d8bcdb630",
|
| 1179 |
+
"source_object_id": "objaverse-1034cd8e4df5430cb874f012415a43b0"
|
| 1180 |
+
},
|
| 1181 |
+
{
|
| 1182 |
+
"repo": "allenai/objaverse",
|
| 1183 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1184 |
+
"path": "glbs/000-001/3c1bae0687144f51861a8a52be036c2b.glb",
|
| 1185 |
+
"asset_id": "3c1bae0687144f51861a8a52be036c2b",
|
| 1186 |
+
"object_id": "objaverse-3c1bae0687144f51861a8a52be036c2b",
|
| 1187 |
+
"license": "cc0-1.0",
|
| 1188 |
+
"author": "Virtual Museums of Ma\u0142opolska",
|
| 1189 |
+
"title": "A Statue of Saint Stanislaus",
|
| 1190 |
+
"source_url": "https://sketchfab.com/3d-models/3c1bae0687144f51861a8a52be036c2b",
|
| 1191 |
+
"sha256": "7d5415ff3734d5c7ee9cf832575829544b18ca348081a09bfd451cefb0a48bc4",
|
| 1192 |
+
"source_object_id": "objaverse-3c1bae0687144f51861a8a52be036c2b"
|
| 1193 |
+
},
|
| 1194 |
+
{
|
| 1195 |
+
"repo": "allenai/objaverse",
|
| 1196 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1197 |
+
"path": "glbs/000-000/0c16db638e0a45f2b4cbcb87fe455e6a.glb",
|
| 1198 |
+
"asset_id": "0c16db638e0a45f2b4cbcb87fe455e6a",
|
| 1199 |
+
"object_id": "objaverse-0c16db638e0a45f2b4cbcb87fe455e6a",
|
| 1200 |
+
"license": "cc0-1.0",
|
| 1201 |
+
"author": "Virtual Museums of Ma\u0142opolska",
|
| 1202 |
+
"title": "A twin capital with decoration of plant motifs",
|
| 1203 |
+
"source_url": "https://sketchfab.com/3d-models/0c16db638e0a45f2b4cbcb87fe455e6a",
|
| 1204 |
+
"sha256": "e012cf77e231d3d2344a6e02bcebfb496cf1b8d0b8ba3e9da5b936ed2f89d8e7",
|
| 1205 |
+
"source_object_id": "objaverse-0c16db638e0a45f2b4cbcb87fe455e6a"
|
| 1206 |
+
},
|
| 1207 |
+
{
|
| 1208 |
+
"repo": "allenai/objaverse",
|
| 1209 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1210 |
+
"path": "glbs/000-000/dcd2f3f53bab48899cb0aaefefc9d9d5.glb",
|
| 1211 |
+
"asset_id": "dcd2f3f53bab48899cb0aaefefc9d9d5",
|
| 1212 |
+
"object_id": "objaverse-dcd2f3f53bab48899cb0aaefefc9d9d5",
|
| 1213 |
+
"license": "cc0-1.0",
|
| 1214 |
+
"author": "Virtual Museums of Ma\u0142opolska",
|
| 1215 |
+
"title": "Vodka distillation set",
|
| 1216 |
+
"source_url": "https://sketchfab.com/3d-models/dcd2f3f53bab48899cb0aaefefc9d9d5",
|
| 1217 |
+
"sha256": "7e8878f3b4fd65e80dd7e16fa06b27e6800881e487b3bccfc319d416b56b0df1",
|
| 1218 |
+
"source_object_id": "objaverse-dcd2f3f53bab48899cb0aaefefc9d9d5"
|
| 1219 |
+
},
|
| 1220 |
+
{
|
| 1221 |
+
"repo": "allenai/objaverse",
|
| 1222 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1223 |
+
"path": "glbs/000-006/dd64acda343d4e38a8023285b89175c3.glb",
|
| 1224 |
+
"asset_id": "dd64acda343d4e38a8023285b89175c3",
|
| 1225 |
+
"object_id": "objaverse-dd64acda343d4e38a8023285b89175c3",
|
| 1226 |
+
"license": "cc0-1.0",
|
| 1227 |
+
"author": "Minneapolis Institute of Art",
|
| 1228 |
+
"title": "Mina'i 'Bowl Depicting a Seated King,' 12th C CE",
|
| 1229 |
+
"source_url": "https://sketchfab.com/3d-models/dd64acda343d4e38a8023285b89175c3",
|
| 1230 |
+
"sha256": "a65ae2df9165b95cd0f01b5ae0bcfe24176bf0935f355e02cd7d335e8fba04bf",
|
| 1231 |
+
"source_object_id": "objaverse-dd64acda343d4e38a8023285b89175c3"
|
| 1232 |
+
},
|
| 1233 |
+
{
|
| 1234 |
+
"repo": "allenai/objaverse",
|
| 1235 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1236 |
+
"path": "glbs/000-004/2d85ff6291f343e5bf062023f3c33afb.glb",
|
| 1237 |
+
"asset_id": "2d85ff6291f343e5bf062023f3c33afb",
|
| 1238 |
+
"object_id": "objaverse-2d85ff6291f343e5bf062023f3c33afb",
|
| 1239 |
+
"license": "cc0-1.0",
|
| 1240 |
+
"author": "Digital Atlas of Ancient Life",
|
| 1241 |
+
"title": "Bryozoan: Archimedes oweniana (PRI 45535)",
|
| 1242 |
+
"source_url": "https://sketchfab.com/3d-models/2d85ff6291f343e5bf062023f3c33afb",
|
| 1243 |
+
"sha256": "d18ee5e1d0b6343d71bc5e90652b58d7c4650c492121c44aef7a9f8401783d1a",
|
| 1244 |
+
"source_object_id": "objaverse-2d85ff6291f343e5bf062023f3c33afb"
|
| 1245 |
+
},
|
| 1246 |
+
{
|
| 1247 |
+
"repo": "allenai/objaverse",
|
| 1248 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1249 |
+
"path": "glbs/000-005/cd14b616da35470eae6894259697314c.glb",
|
| 1250 |
+
"asset_id": "cd14b616da35470eae6894259697314c",
|
| 1251 |
+
"object_id": "objaverse-cd14b616da35470eae6894259697314c",
|
| 1252 |
+
"license": "cc0-1.0",
|
| 1253 |
+
"author": "Digital Atlas of Ancient Life",
|
| 1254 |
+
"title": "Bivalve: Nodipecten pernodosus (PRI 44328)",
|
| 1255 |
+
"source_url": "https://sketchfab.com/3d-models/cd14b616da35470eae6894259697314c",
|
| 1256 |
+
"sha256": "b27e76c2ec4cbfe038f5cefe1ed2f3c4120eb7b42014a97f086098a392160ce5",
|
| 1257 |
+
"source_object_id": "objaverse-cd14b616da35470eae6894259697314c"
|
| 1258 |
+
},
|
| 1259 |
+
{
|
| 1260 |
+
"repo": "allenai/objaverse",
|
| 1261 |
+
"revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
|
| 1262 |
+
"path": "glbs/000-007/0994815e0a994ee69c2e408860d17cee.glb",
|
| 1263 |
+
"asset_id": "0994815e0a994ee69c2e408860d17cee",
|
| 1264 |
+
"object_id": "objaverse-0994815e0a994ee69c2e408860d17cee",
|
| 1265 |
+
"license": "cc0-1.0",
|
| 1266 |
+
"author": "Virtual Museums of Ma\u0142opolska",
|
| 1267 |
+
"title": "Silver salt cellar with a figure of a boy",
|
| 1268 |
+
"source_url": "https://sketchfab.com/3d-models/0994815e0a994ee69c2e408860d17cee",
|
| 1269 |
+
"sha256": "9dec787850e4e5b418aeb031048f818563f76432896c0922fb444dcf6c5ad311",
|
| 1270 |
+
"source_object_id": "objaverse-0994815e0a994ee69c2e408860d17cee"
|
| 1271 |
+
},
|
| 1272 |
+
{
|
| 1273 |
+
"repo": "scenario-labs/3d-collection",
|
| 1274 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 1275 |
+
"path": "assets/scenario_asset_PxAmvCzSumrBKsUwQdALmCVb/output.glb",
|
| 1276 |
+
"sha256": "c264e82d7aff627b33f79e90adcb36acfc73a85b2911aac3b08a9181bfe52001",
|
| 1277 |
+
"asset_id": "scenario:asset_PxAmvCzSumrBKsUwQdALmCVb",
|
| 1278 |
+
"license": "cc-by-4.0",
|
| 1279 |
+
"author": "Scenario",
|
| 1280 |
+
"title": "scenario:asset_PxAmvCzSumrBKsUwQdALmCVb",
|
| 1281 |
+
"source_model": "model_trellis",
|
| 1282 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 1283 |
+
"object_id": "scenario-5002697c4e9509fe4da7",
|
| 1284 |
+
"source_object_id": "scenario-5002697c4e9509fe4da7"
|
| 1285 |
+
},
|
| 1286 |
+
{
|
| 1287 |
+
"repo": "scenario-labs/3d-collection",
|
| 1288 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 1289 |
+
"path": "assets/d3873915ce9e9250/12097a943346f264.glb",
|
| 1290 |
+
"sha256": "39021e31a04464c89faee8d13a9fe996a793f5d57ae177da6c948e040fc55070",
|
| 1291 |
+
"asset_id": "d3873915ce9e9250",
|
| 1292 |
+
"license": "cc-by-4.0",
|
| 1293 |
+
"author": "Scenario",
|
| 1294 |
+
"title": "d3873915ce9e9250",
|
| 1295 |
+
"source_model": "claude-opus-5-5",
|
| 1296 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 1297 |
+
"object_id": "scenario-a76f41b9cbac02843bdd",
|
| 1298 |
+
"source_object_id": "scenario-a76f41b9cbac02843bdd"
|
| 1299 |
+
},
|
| 1300 |
+
{
|
| 1301 |
+
"repo": "scenario-labs/3d-collection",
|
| 1302 |
+
"revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
|
| 1303 |
+
"path": "assets/scenario_asset_Yn4bLidfau88DtfBs3aQZ8GA/output.glb",
|
| 1304 |
+
"sha256": "63fce3dfe0d50d8b9fd807119907d420286e58c56e331ef8989e24498e396982",
|
| 1305 |
+
"asset_id": "scenario:asset_Yn4bLidfau88DtfBs3aQZ8GA",
|
| 1306 |
+
"license": "cc-by-4.0",
|
| 1307 |
+
"author": "Scenario",
|
| 1308 |
+
"title": "scenario:asset_Yn4bLidfau88DtfBs3aQZ8GA",
|
| 1309 |
+
"source_model": "model_tripo-v2-5-multiview-to-3d",
|
| 1310 |
+
"source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
|
| 1311 |
+
"object_id": "scenario-b450f77df85a147a528c",
|
| 1312 |
+
"source_object_id": "scenario-b450f77df85a147a528c"
|
| 1313 |
+
}
|
| 1314 |
+
]
|
COMMANDS.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Mac commands
|
| 2 |
+
|
| 3 |
+
Run these in macOS Terminal, from the extracted `forma3d` folder. Requires Apple
|
| 4 |
+
Silicon and Python 3.11 (the setup script lets uv manage Python). If `uv` is not
|
| 5 |
+
installed, run `brew install uv` first. Do not paste Hugging Face tokens into chat.
|
| 6 |
+
|
| 7 |
+
```bash
|
| 8 |
+
bash setup-mac.sh
|
| 9 |
+
source "$HOME/Library/Application Support/Forma3D/venv/bin/activate"
|
| 10 |
+
hf auth login
|
| 11 |
+
hf auth whoami
|
| 12 |
+
|
| 13 |
+
# Pin the original checkpoint so the run is reproducible.
|
| 14 |
+
hf download Lucasgitguy-co/image3d-student \
|
| 15 |
+
examples/synthetic-smoke/synthetic-only.pt \
|
| 16 |
+
--revision 1738cdfaf1bb940bf576a96d11b742ce014b9139 \
|
| 17 |
+
--local-dir base
|
| 18 |
+
|
| 19 |
+
# 96 mesh assets, four canonical rendered views per object.
|
| 20 |
+
# Dataset files and original meshes stay on your machine.
|
| 21 |
+
python scripts/prepare_hf.py \
|
| 22 |
+
--out data/forma3d-v1 --cache data/downloads \
|
| 23 |
+
--scenario 64 --objaverse 32 --objaverse-shards 8 --resume \
|
| 24 |
+
--grid 16 --views 4 --max-file-mb 16 --max-download-mb 2048
|
| 25 |
+
|
| 26 |
+
# The base checkpoint width is 64. All learned weights are loaded.
|
| 27 |
+
# Use a NEW --out directory for every run.
|
| 28 |
+
caffeinate -i image3d train \
|
| 29 |
+
--manifest data/forma3d-v1/manifest.jsonl \
|
| 30 |
+
--init-from base/examples/synthetic-smoke/synthetic-only.pt \
|
| 31 |
+
--out runs/forma3d-v1 --device mps \
|
| 32 |
+
--width 64 --steps 5000 --batch-size 2 --lr 0.0001 \
|
| 33 |
+
--eval-every 100 --validation-fraction 0.2 --seed 42
|
| 34 |
+
|
| 35 |
+
# Independent held-out evaluation, release packaging, then publication.
|
| 36 |
+
python scripts/release.py \
|
| 37 |
+
--run runs/forma3d-v1 --data data/forma3d-v1 \
|
| 38 |
+
--base base/examples/synthetic-smoke/synthetic-only.pt \
|
| 39 |
+
--release release/forma3d-v1 --device mps \
|
| 40 |
+
--repo Lucasgitguy-co/forma3d-tiny --publish
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
The last command requires a Hugging Face token with permission to create and write
|
| 44 |
+
model repositories. It creates a private repository, uploads the complete evaluated
|
| 45 |
+
release, and makes it public only after a successful upload. It refuses to overwrite
|
| 46 |
+
an existing repository. If an upload fails, a private partial repository can remain;
|
| 47 |
+
inspect it before retrying. No raw source datasets or authentication files are uploaded.
|
| 48 |
+
|
| 49 |
+
For a fresh run, the same sequence is available as one command:
|
| 50 |
+
|
| 51 |
+
```bash
|
| 52 |
+
caffeinate -i bash train-mac.sh --publish
|
| 53 |
+
```
|
| 54 |
+
|
| 55 |
+
This reuses the runtime in `~/Library/Application Support/Forma3D/venv`, creating it
|
| 56 |
+
only if missing. It uses that interpreter explicitly and verifies/reuses the local
|
| 57 |
+
base checkpoint. With the dataset already prepared, training needs no Hugging Face
|
| 58 |
+
connection. Publication still requires service availability and your saved HF login.
|
| 59 |
+
Use `bash setup-mac.sh` explicitly when installing updated package source.
|
| 60 |
+
Dataset preparation now verifies and resumes completed objects, including the old
|
| 61 |
+
64-Scenario/28-Objaverse shortage. It saves progress after each object and searches
|
| 62 |
+
eight Objaverse metadata shards. Completely black rendered objects are replaced;
|
| 63 |
+
exact image/target duplicates remain in the same object group. Excluded existing
|
| 64 |
+
files are preserved but omitted from the manifests. If preparation stops, rerun the same command.
|
| 65 |
+
Training and release directories still must be fresh; after training has started,
|
| 66 |
+
follow the individual commands from the failed stage. The wrapper does not resume
|
| 67 |
+
optimizer state. Downloaded meshes remain cached in `data/downloads`.
|
| 68 |
+
|
| 69 |
+
Publication requires completed optimizer steps, lower validation and independent
|
| 70 |
+
test loss than the starting checkpoint, higher test occupancy IoU, test IoU at least
|
| 71 |
+
0.05, and nonempty qualitative predictions. These are baseline research checks,
|
| 72 |
+
not proof of production quality. A failed gate writes `runs/forma3d-v1/evaluation.json`
|
| 73 |
+
and does not publish. Inspect the generated PNG comparisons in `runs/forma3d-v1/inspection`.
|
| 74 |
+
|
| 75 |
+
To inspect first without publishing, omit `--publish`. When subsequently publishing,
|
| 76 |
+
use a fresh `--release` directory. The evaluation is repeated against the actual weights.
|
| 77 |
+
|
| 78 |
+
To test inference after training:
|
| 79 |
+
|
| 80 |
+
```bash
|
| 81 |
+
image3d generate --checkpoint runs/forma3d-v1/best.pt \
|
| 82 |
+
--image your-centered-cutout.png --out results/object.ply --device mps
|
| 83 |
+
image3d preview --ply results/object.ply --out results/preview.png
|
| 84 |
+
```
|
| 85 |
+
|
| 86 |
+
Replace `your-centered-cutout.png` with a real file. Output is Gaussian PLY, not GLB
|
| 87 |
+
or a triangle mesh. Real photos are outside the tested proxy-render distribution.
|
| 88 |
+
|
| 89 |
+
For a larger experiment, increase object counts, shard count and download budget
|
| 90 |
+
in a fresh dataset directory after checking free disk space. Source metadata is
|
| 91 |
+
pinned, selection is deterministic, and all views/known shared inputs stay grouped.
|
| 92 |
+
The starter run is not a claim that 96 objects or 5,000 steps are enough for strong
|
| 93 |
+
generalization. Training time depends on the Mac and is not yet benchmarked for
|
| 94 |
+
the full recipe. `Ctrl-C` saves `last.pt`; `--init-from runs/forma3d-v1/last.pt`
|
| 95 |
+
starts a fresh optimizer in a new output directory and is not exact resume.
|
| 96 |
+
|
| 97 |
+
If Terminal cannot use Metal, `--device mps` fails explicitly. `--device cpu` is
|
| 98 |
+
available for small tests and Intel Macs but is much slower. Keep the selected
|
| 99 |
+
device consistent in training and evaluation commands.
|
| 100 |
+
|
| 101 |
+
## Local runtime repair — 2026-11-03
|
| 102 |
+
|
| 103 |
+
The previous `.venv` under Documents contained offloaded (`dataless`) files, causing
|
| 104 |
+
Python read timeouts. The runtime now lives under Library/Application Support and
|
| 105 |
+
uses a regular package installation rather than an editable `.pth` link. The old
|
| 106 |
+
`.venv`, source data, and checkpoints are preserved.
|
| 107 |
+
|
| 108 |
+
A Hugging Face 503 can prevent browsing or publishing without affecting local
|
| 109 |
+
training. Wait and retry the evaluation/publish step when the service is available;
|
| 110 |
+
do not rerun completed training. Use a new `--release` directory when restaging.
|
DATASETS.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Data selection and attribution
|
| 2 |
+
|
| 3 |
+
Reviewed 2026-11-02. User requested commercial-use-compatible data and exclusion
|
| 4 |
+
of noncommercial datasets. This recipe uses only the sources explicitly marked
|
| 5 |
+
included below. Repository-level labels do not replace individual asset terms.
|
| 6 |
+
|
| 7 |
+
| Source | Status | Reason |
|
| 8 |
+
|---|---|---|
|
| 9 |
+
| [scenario-labs/3d-collection](https://huggingface.co/datasets/scenario-labs/3d-collection) | Included, bounded GLB subset | Explicit CC-BY-4.0 row filter; Hunyuan-labeled models excluded; checksums verified against metadata. Attribution: Scenario; modifications: normalization, surface sampling, Gaussian proxy rendering. |
|
| 10 |
+
| [scenario-labs/3d-collection-hunyuan](https://huggingface.co/datasets/scenario-labs/3d-collection-hunyuan) | Excluded | Dataset expressly prohibits using assets to train or improve AI models. |
|
| 11 |
+
| [3dlg-hcvc/MultiScan](https://huggingface.co/datasets/3dlg-hcvc/MultiScan) | Excluded | CC-BY-NC-4.0, gated scene data. |
|
| 12 |
+
| [huanngzh/3D-Front](https://huggingface.co/datasets/huanngzh/3D-Front) | Excluded | CC-BY-NC-4.0, indoor scenes rather than directly aligned object targets. |
|
| 13 |
+
| [facebook/show3d-dataset](https://huggingface.co/datasets/facebook/show3d-dataset) | Excluded | CC-BY-NC-4.0; interaction/video data needs a separate task-specific pipeline. |
|
| 14 |
+
| [Voxel51/gaussian_splatting](https://huggingface.co/datasets/Voxel51/gaussian_splatting) | Deferred; not used | Card labels Apache-2.0 and describes a few scene reconstructions. This object-centered recipe does not establish camera alignment, object crops, or source-scene rights from the card alone. No importer or download is provided. |
|
| 15 |
+
| [allenai/objaverse](https://huggingface.co/datasets/allenai/objaverse) | Added: CC0 assets only | Dataset compilation is ODC-By; assets have separate licenses. Script accepts only individual `cc0` metadata entries, retains author/title/source links, and excludes animated assets. |
|
| 16 |
+
| [allenai/objaverse-xl](https://huggingface.co/datasets/allenai/objaverse-xl) | Future candidate; not used | Heterogeneous per-file licensing; no blanket commercial-use assumption or importer in this kit. |
|
| 17 |
+
|
| 18 |
+
Pinned revisions:
|
| 19 |
+
|
| 20 |
+
- Scenario: `55b4c002b4c1529fc48da3dff98516c3069bfa3f`
|
| 21 |
+
- Objaverse: `556637099bf4fa79ea7b239d0d9c328b8a2e9ac8`
|
| 22 |
+
- Original model: `1738cdfaf1bb940bf576a96d11b742ce014b9139`
|
| 23 |
+
|
| 24 |
+
The actual asset inventory is generated as `sources.json`, with asset IDs, source
|
| 25 |
+
URLs, authors, licenses, revision IDs and SHA-256 hashes. Published releases copy
|
| 26 |
+
this file to `ATTRIBUTIONS.json`. Keep it with the released model. Rejected assets
|
| 27 |
+
are recorded in `skipped.json`. The model card must not list excluded or merely
|
| 28 |
+
considered datasets as training sources.
|
| 29 |
+
|
| 30 |
+
License references: [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/),
|
| 31 |
+
[CC0](https://creativecommons.org/publicdomain/zero/1.0/),
|
| 32 |
+
[ODC-By](https://opendatacommons.org/licenses/by/1-0/).
|
LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
Apache License
|
| 3 |
+
Version 2.0, January 2004
|
| 4 |
+
http://www.apache.org/licenses/
|
| 5 |
+
|
| 6 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
| 7 |
+
|
| 8 |
+
1. Definitions.
|
| 9 |
+
|
| 10 |
+
"License" shall mean the terms and conditions for use, reproduction,
|
| 11 |
+
and distribution as defined by Sections 1 through 9 of this document.
|
| 12 |
+
|
| 13 |
+
"Licensor" shall mean the copyright owner or entity authorized by
|
| 14 |
+
the copyright owner that is granting the License.
|
| 15 |
+
|
| 16 |
+
"Legal Entity" shall mean the union of the acting entity and all
|
| 17 |
+
other entities that control, are controlled by, or are under common
|
| 18 |
+
control with that entity. For the purposes of this definition,
|
| 19 |
+
"control" means (i) the power, direct or indirect, to cause the
|
| 20 |
+
direction or management of such entity, whether by contract or
|
| 21 |
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
| 22 |
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
| 23 |
+
|
| 24 |
+
"You" (or "Your") shall mean an individual or Legal Entity
|
| 25 |
+
exercising permissions granted by this License.
|
| 26 |
+
|
| 27 |
+
"Source" form shall mean the preferred form for making modifications,
|
| 28 |
+
including but not limited to software source code, documentation
|
| 29 |
+
source, and configuration files.
|
| 30 |
+
|
| 31 |
+
"Object" form shall mean any form resulting from mechanical
|
| 32 |
+
transformation or translation of a Source form, including but
|
| 33 |
+
not limited to compiled object code, generated documentation,
|
| 34 |
+
and conversions to other media types.
|
| 35 |
+
|
| 36 |
+
"Work" shall mean the work of authorship, whether in Source or
|
| 37 |
+
Object form, made available under the License, as indicated by a
|
| 38 |
+
copyright notice that is included in or attached to the work
|
| 39 |
+
(an example is provided in the Appendix below).
|
| 40 |
+
|
| 41 |
+
"Derivative Works" shall mean any work, whether in Source or Object
|
| 42 |
+
form, that is based on (or derived from) the Work and for which the
|
| 43 |
+
editorial revisions, annotations, elaborations, or other modifications
|
| 44 |
+
represent, as a whole, an original work of authorship. For the purposes
|
| 45 |
+
of this License, Derivative Works shall not include works that remain
|
| 46 |
+
separable from, or merely link (or bind by name) to the interfaces of,
|
| 47 |
+
the Work and Derivative Works thereof.
|
| 48 |
+
|
| 49 |
+
"Contribution" shall mean any work of authorship, including
|
| 50 |
+
the original version of the Work and any modifications or additions
|
| 51 |
+
to that Work or Derivative Works thereof, that is intentionally
|
| 52 |
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
| 53 |
+
or by an individual or Legal Entity authorized to submit on behalf of
|
| 54 |
+
the copyright owner. For the purposes of this definition, "submitted"
|
| 55 |
+
means any form of electronic, verbal, or written communication sent
|
| 56 |
+
to the Licensor or its representatives, including but not limited to
|
| 57 |
+
communication on electronic mailing lists, source code control systems,
|
| 58 |
+
and issue tracking systems that are managed by, or on behalf of, the
|
| 59 |
+
Licensor for the purpose of discussing and improving the Work, but
|
| 60 |
+
excluding communication that is conspicuously marked or otherwise
|
| 61 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
| 62 |
+
|
| 63 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
| 64 |
+
on behalf of whom a Contribution has been received by Licensor and
|
| 65 |
+
subsequently incorporated within the Work.
|
| 66 |
+
|
| 67 |
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
| 68 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 69 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 70 |
+
copyright license to reproduce, prepare Derivative Works of,
|
| 71 |
+
publicly display, publicly perform, sublicense, and distribute the
|
| 72 |
+
Work and such Derivative Works in Source or Object form.
|
| 73 |
+
|
| 74 |
+
3. Grant of Patent License. Subject to the terms and conditions of
|
| 75 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 76 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 77 |
+
(except as stated in this section) patent license to make, have made,
|
| 78 |
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
| 79 |
+
where such license applies only to those patent claims licensable
|
| 80 |
+
by such Contributor that are necessarily infringed by their
|
| 81 |
+
Contribution(s) alone or by combination of their Contribution(s)
|
| 82 |
+
with the Work to which such Contribution(s) was submitted. If You
|
| 83 |
+
institute patent litigation against any entity (including a
|
| 84 |
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
| 85 |
+
or a Contribution incorporated within the Work constitutes direct
|
| 86 |
+
or contributory patent infringement, then any patent licenses
|
| 87 |
+
granted to You under this License for that Work shall terminate
|
| 88 |
+
as of the date such litigation is filed.
|
| 89 |
+
|
| 90 |
+
4. Redistribution. You may reproduce and distribute copies of the
|
| 91 |
+
Work or Derivative Works thereof in any medium, with or without
|
| 92 |
+
modifications, and in Source or Object form, provided that You
|
| 93 |
+
meet the following conditions:
|
| 94 |
+
|
| 95 |
+
(a) You must give any other recipients of the Work or
|
| 96 |
+
Derivative Works a copy of this License; and
|
| 97 |
+
|
| 98 |
+
(b) You must cause any modified files to carry prominent notices
|
| 99 |
+
stating that You changed the files; and
|
| 100 |
+
|
| 101 |
+
(c) You must retain, in the Source form of any Derivative Works
|
| 102 |
+
that You distribute, all copyright, patent, trademark, and
|
| 103 |
+
attribution notices from the Source form of the Work,
|
| 104 |
+
excluding those notices that do not pertain to any part of
|
| 105 |
+
the Derivative Works; and
|
| 106 |
+
|
| 107 |
+
(d) If the Work includes a "NOTICE" text file as part of its
|
| 108 |
+
distribution, then any Derivative Works that You distribute must
|
| 109 |
+
include a readable copy of the attribution notices contained
|
| 110 |
+
within such NOTICE file, excluding those notices that do not
|
| 111 |
+
pertain to any part of the Derivative Works, in at least one
|
| 112 |
+
of the following places: within a NOTICE text file distributed
|
| 113 |
+
as part of the Derivative Works; within the Source form or
|
| 114 |
+
documentation, if provided along with the Derivative Works; or,
|
| 115 |
+
within a display generated by the Derivative Works, if and
|
| 116 |
+
wherever such third-party notices normally appear. The contents
|
| 117 |
+
of the NOTICE file are for informational purposes only and
|
| 118 |
+
do not modify the License. You may add Your own attribution
|
| 119 |
+
notices within Derivative Works that You distribute, alongside
|
| 120 |
+
or as an addendum to the NOTICE text from the Work, provided
|
| 121 |
+
that such additional attribution notices cannot be construed
|
| 122 |
+
as modifying the License.
|
| 123 |
+
|
| 124 |
+
You may add Your own copyright statement to Your modifications and
|
| 125 |
+
may provide additional or different license terms and conditions
|
| 126 |
+
for use, reproduction, or distribution of Your modifications, or
|
| 127 |
+
for any such Derivative Works as a whole, provided Your use,
|
| 128 |
+
reproduction, and distribution of the Work otherwise complies with
|
| 129 |
+
the conditions stated in this License.
|
| 130 |
+
|
| 131 |
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
| 132 |
+
any Contribution intentionally submitted for inclusion in the Work
|
| 133 |
+
by You to the Licensor shall be under the terms and conditions of
|
| 134 |
+
this License, without any additional terms or conditions.
|
| 135 |
+
Notwithstanding the above, nothing herein shall supersede or modify
|
| 136 |
+
the terms of any separate license agreement you may have executed
|
| 137 |
+
with Licensor regarding such Contributions.
|
| 138 |
+
|
| 139 |
+
6. Trademarks. This License does not grant permission to use the trade
|
| 140 |
+
names, trademarks, service marks, or product names of the Licensor,
|
| 141 |
+
except as required for reasonable and customary use in describing the
|
| 142 |
+
origin of the Work and reproducing the content of the NOTICE file.
|
| 143 |
+
|
| 144 |
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
| 145 |
+
agreed to in writing, Licensor provides the Work (and each
|
| 146 |
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
| 147 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
| 148 |
+
implied, including, without limitation, any warranties or conditions
|
| 149 |
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
| 150 |
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
| 151 |
+
appropriateness of using or redistributing the Work and assume any
|
| 152 |
+
risks associated with Your exercise of permissions under this License.
|
| 153 |
+
|
| 154 |
+
8. Limitation of Liability. In no event and under no legal theory,
|
| 155 |
+
whether in tort (including negligence), contract, or otherwise,
|
| 156 |
+
unless required by applicable law (such as deliberate and grossly
|
| 157 |
+
negligent acts) or agreed to in writing, shall any Contributor be
|
| 158 |
+
liable to You for damages, including any direct, indirect, special,
|
| 159 |
+
incidental, or consequential damages of any character arising as a
|
| 160 |
+
result of this License or out of the use or inability to use the
|
| 161 |
+
Work (including but not limited to damages for loss of goodwill,
|
| 162 |
+
work stoppage, computer failure or malfunction, or any and all
|
| 163 |
+
other commercial damages or losses), even if such Contributor
|
| 164 |
+
has been advised of the possibility of such damages.
|
| 165 |
+
|
| 166 |
+
9. Accepting Warranty or Additional Liability. While redistributing
|
| 167 |
+
the Work or Derivative Works thereof, You may choose to offer,
|
| 168 |
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
| 169 |
+
or other liability obligations and/or rights consistent with this
|
| 170 |
+
License. However, in accepting such obligations, You may act only
|
| 171 |
+
on Your own behalf and on Your sole responsibility, not on behalf
|
| 172 |
+
of any other Contributor, and only if You agree to indemnify,
|
| 173 |
+
defend, and hold each Contributor harmless for any liability
|
| 174 |
+
incurred by, or claims asserted against, such Contributor by reason
|
| 175 |
+
of your accepting any such warranty or additional liability.
|
| 176 |
+
|
| 177 |
+
END OF TERMS AND CONDITIONS
|
| 178 |
+
|
| 179 |
+
APPENDIX: How to apply the Apache License to your work.
|
| 180 |
+
|
| 181 |
+
To apply the Apache License to your work, attach the following
|
| 182 |
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
| 183 |
+
replaced with your own identifying information. (Don't include
|
| 184 |
+
the brackets!) The text should be enclosed in the appropriate
|
| 185 |
+
comment syntax for the file format. We also recommend that a
|
| 186 |
+
file or class name and description of purpose be included on the
|
| 187 |
+
same "printed page" as the copyright notice for easier
|
| 188 |
+
identification within third-party archives.
|
| 189 |
+
|
| 190 |
+
Copyright [yyyy] [name of copyright owner]
|
| 191 |
+
|
| 192 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 193 |
+
you may not use this file except in compliance with the License.
|
| 194 |
+
You may obtain a copy of the License at
|
| 195 |
+
|
| 196 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
| 197 |
+
|
| 198 |
+
Unless required by applicable law or agreed to in writing, software
|
| 199 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 200 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 201 |
+
See the License for the specific language governing permissions and
|
| 202 |
+
limitations under the License.
|
NOTICE
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Forma3D-Tiny v0.2.0, derived from Image3D Student v0.1.0
|
| 2 |
+
Copyright 2026 Lucasgitguy-co.
|
| 3 |
+
|
| 4 |
+
Original project source, documentation and procedural demonstration artifacts are released under Apache License 2.0.
|
| 5 |
+
|
| 6 |
+
The optional Idol integration and Gaussian attribute conventions were developed with reference to
|
| 7 |
+
speridlabs/idol-sdk, revision 4702a7f00850e34b6e83a2170cc123c3e9570744 (Apache-2.0).
|
| 8 |
+
Its architecture is imported as an optional dependency; pretrained teacher weights are not redistributed.
|
| 9 |
+
Adaptations in this project: staged loading, query-chunk attention, explicit real-valued RoPE selection,
|
| 10 |
+
independent student training, coordinate-preserving Gaussian IO, and diagnostic rendering.
|
| 11 |
+
Upstream attribution is retained in licenses/Idol-APACHE-2.0.txt and THIRD_PARTY.md.
|
README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
pipeline_tag: image-to-3d
|
| 4 |
+
base_model: Lucasgitguy-co/image3d-student
|
| 5 |
+
model_name: Forma3D-Tiny v0.2
|
| 6 |
+
datasets:
|
| 7 |
+
- allenai/objaverse
|
| 8 |
+
- scenario-labs/3d-collection
|
| 9 |
+
tags:
|
| 10 |
+
- pytorch
|
| 11 |
+
- gaussian-splatting
|
| 12 |
+
- research-prototype
|
| 13 |
+
- mesh-proxy-supervision
|
| 14 |
+
---
|
| 15 |
+
# Forma3D-Tiny v0.2
|
| 16 |
+
|
| 17 |
+
An experimental compact image-to-Gaussian model post-trained from Image3D Student's
|
| 18 |
+
synthetic demonstration checkpoint. This is a coarse research baseline, not a
|
| 19 |
+
general-purpose photo-to-3D model. Its grid is 16 cubed and
|
| 20 |
+
it has 306,321 parameters. Selected checkpoint: step 4800;
|
| 21 |
+
completed run: 5000 steps.
|
| 22 |
+
|
| 23 |
+
## Actual training data and preprocessing
|
| 24 |
+
|
| 25 |
+
Only the datasets listed above were used, with per-asset provenance in ATTRIBUTIONS.json.
|
| 26 |
+
Scenario assets are CC-BY-4.0; the Objaverse subset is CC0. Original objects were centered
|
| 27 |
+
and uniformly scaled into a 0.9-wide cube, surface sampled, and converted to isotropic
|
| 28 |
+
Gaussian proxy targets. Orthographic images were rendered from these same proxy clouds.
|
| 29 |
+
This is not teacher distillation from Idol, Hunyuan, InstantMesh, or Hi3D, and it did not
|
| 30 |
+
train on natural photographs, MultiScan, 3D-Front, Show3D, or Voxel51 scene splats.
|
| 31 |
+
|
| 32 |
+
Related source inputs and all views stay in the same object group. A separate 15% test
|
| 33 |
+
partition is excluded from training and validation-based checkpoint selection.
|
| 34 |
+
|
| 35 |
+
## Measured results
|
| 36 |
+
|
| 37 |
+
Independent test objects: 14; test views: 60.
|
| 38 |
+
Base test loss: 0.842823; post-trained test loss:
|
| 39 |
+
0.584055. Base occupancy IoU:
|
| 40 |
+
0.272567; post-trained occupancy IoU:
|
| 41 |
+
0.307005.
|
| 42 |
+
See evaluation.json for the full results and checks. These scores measure coarse proxy
|
| 43 |
+
reconstruction on the rendered data distribution; they do not prove photo realism,
|
| 44 |
+
watertight meshes, production quality, or texture fidelity. Near duplicates can remain
|
| 45 |
+
despite source grouping and exact-byte deduplication.
|
| 46 |
+
|
| 47 |
+
## Run on a Mac
|
| 48 |
+
|
| 49 |
+
Download this repository, then run `bash setup-mac.sh` and
|
| 50 |
+
`source "$HOME/Library/Application Support/Forma3D/venv/bin/activate"`.
|
| 51 |
+
|
| 52 |
+
```sh
|
| 53 |
+
image3d generate --checkpoint model.pt --image your-centered-cutout.png \
|
| 54 |
+
--out results/object.ply --device mps
|
| 55 |
+
image3d preview --ply results/object.ply --out results/preview.png
|
| 56 |
+
```
|
| 57 |
+
|
| 58 |
+
Inputs are centered objects on black, matching the training framing. Natural photos
|
| 59 |
+
are outside the verified distribution. Output is Gaussian PLY, not a triangle mesh.
|
| 60 |
+
CPU works with `--device cpu`; CUDA support is implemented but was not tested on the
|
| 61 |
+
Mac used to prepare these scripts.
|
| 62 |
+
|
| 63 |
+
## License and attribution
|
| 64 |
+
|
| 65 |
+
Source code and these weights are offered under Apache-2.0. Dataset and individual
|
| 66 |
+
asset licenses remain separate; retain ATTRIBUTIONS.json and consult DATASETS.md.
|
| 67 |
+
This license statement does not grant rights to third-party trademarks or likenesses.
|
| 68 |
+
See COMMANDS.md for reproduction commands.
|
SHA256SUMS
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
a9ba265d76a139fa5e7d95a3176e6d6053e811cc722afe11ab5ae5dac61cfa14 ATTRIBUTIONS.json
|
| 2 |
+
9988ea29538b73886bfc1fd404edcf5bb64b7acfc7586fa6b7430ce13d02cb4b COMMANDS.md
|
| 3 |
+
4c09bfeb821d41b9da58c9a20c28c4000f40956f4359a04274556436a4ed009f DATASETS.md
|
| 4 |
+
cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30 LICENSE
|
| 5 |
+
05f38086626c05b43280173a453858ff2eb4273d63b554c94492c64f09a20ab3 NOTICE
|
| 6 |
+
b4fbe86b0118756c0f22228868d3815c731dbd02866d0a5a8bbf04e66e832c47 README.md
|
| 7 |
+
ef7c689f184a7921b02887eeb8d859e8cca77da6d2082999bb19bf29beda61f1 THIRD_PARTY.md
|
| 8 |
+
25d53c6500d9e45aca8a2ce1fe54030e05a0822c554ab24cfcbfeaa631ee9c91 config.json
|
| 9 |
+
b838b35d053ec45f9de150414f98a6b329e4f0be52d9a1c1095320050d8b22bb evaluation.json
|
| 10 |
+
cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30 licenses/Idol-APACHE-2.0.txt
|
| 11 |
+
83c065d2a50cf086928542cf8d40dc4416b379e38b9aa61d842dc9106d4b3306 model.pt
|
| 12 |
+
f2beee0eea3e9e76d921fc2b2587df3e55115b7a0e7f331d684b8a32256ebc7d pyproject.toml
|
| 13 |
+
53dc8f90461d899ed8c15574c3e96f9bf07da4d3ee783a47ec3a3b077b6ee9ca requirements-tested-macos.txt
|
| 14 |
+
03325cb525f9e0562865f8df123678a147db38680b024f0845482dc2d5bc1651 scripts/prepare_hf.py
|
| 15 |
+
96f7df49a214e05b86c2d86023d6500986a4d17b2dfe8b23ab7d213d75375fad scripts/release.py
|
| 16 |
+
9eaa2118115870e618fe71e130e3671c419a81ac484c80f30ca89b9e2eb677a5 setup-mac.sh
|
| 17 |
+
c09ce8cb78cd68ae32b618ba49f97508b6ce14bc89e88c5b80cc3e2487bd919c src/image3d_student/__init__.py
|
| 18 |
+
b4be53a864458a84009e91277ff64767dffc6139ca3afcc50526747743722c02 src/image3d_student/cli.py
|
| 19 |
+
d34f9fa50d574764e5e2c1c31c1ca477f2bc4a1887e103c5c47b754f1f1d8c72 src/image3d_student/data.py
|
| 20 |
+
e01d1b42929c993d92cad1bde8944b14c6a8e325fc279d8fd3e9c7287523ad69 src/image3d_student/demo.py
|
| 21 |
+
7335dcc99fcd9cea5c217841376f0ca8c0ca179809b4df34e344bf929d11da51 src/image3d_student/engine.py
|
| 22 |
+
a18005f75a66846446b2574b4f1b085ebde5321e835c4e5b4507e15e812ee5ef src/image3d_student/model.py
|
| 23 |
+
41961fae62d2819c1e3f455e74539a66b8c4f57bedd9fb9379497b3a5764c692 src/image3d_student/splats.py
|
| 24 |
+
2e2439bc0a48c52e32a8e273f879ed7328fdb82632a996ed3e239e0391ca3a59 src/image3d_student/teacher_idol.py
|
| 25 |
+
4487becd424209645b3cc463c3f17a3b3b32abb5fc9c3fd50190cf1122757298 train-mac.sh
|
| 26 |
+
c3478f8a0f1708ff19dccba080e8bb089dcde43a4907dde16d25edff430fe559 training.json
|
THIRD_PARTY.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Third-party scope
|
| 2 |
+
|
| 3 |
+
This training kit extends Lucasgitguy-co/image3d-student, Apache-2.0. The original
|
| 4 |
+
checkpoint is downloaded separately. No new trained weights are bundled in the kit.
|
| 5 |
+
|
| 6 |
+
Optional Idol SDK integration is inherited from the original project, pinned to
|
| 7 |
+
`4702a7f00850e34b6e83a2170cc123c3e9570744`; its Apache notice is retained in
|
| 8 |
+
`licenses/Idol-APACHE-2.0.txt`. The Mac recipe does not install or run Idol, Hi3D,
|
| 9 |
+
InstantMesh, Hunyuan, or gated encoders. Their weights are not redistributed.
|
| 10 |
+
|
| 11 |
+
Dependencies retain their respective licenses. Third-party dataset terms are
|
| 12 |
+
documented in DATASETS.md; per-asset attribution is generated during preparation
|
| 13 |
+
and copied into any published release. Code licensing does not relicense datasets.
|
config.json
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"grid": 16,
|
| 3 |
+
"width": 64
|
| 4 |
+
}
|
evaluation.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"checkpoint_sha256": "449e14a96d3507f7ad8e8c270d1fd632a09e0753254d0bfc93b659832d8b8ca8",
|
| 3 |
+
"base_sha256": "dd1a1719541c5603125e7f9379b0ad8ede20b7e9f2816a04e9120244cdbf528e",
|
| 4 |
+
"test_manifest_sha256": "d29a8be0d5e773874a21e59496b934f3647954213c43f972cf68abbb80dc40df",
|
| 5 |
+
"test_objects": 14,
|
| 6 |
+
"test_samples": 60,
|
| 7 |
+
"baseline_test": {
|
| 8 |
+
"occupancy": 0.5195401266217232,
|
| 9 |
+
"position": 0.11201683692634105,
|
| 10 |
+
"colour": 0.06971513153985143,
|
| 11 |
+
"scale": 0.6968644132216771,
|
| 12 |
+
"rotation": 0.006667846724546204,
|
| 13 |
+
"opacity": 0.0014822189676730582,
|
| 14 |
+
"geometry": 0.0,
|
| 15 |
+
"loss": 0.8428226768970489,
|
| 16 |
+
"occupancy_iou": 0.27256669824322066
|
| 17 |
+
},
|
| 18 |
+
"posttrained_test": {
|
| 19 |
+
"occupancy": 0.4215678572654724,
|
| 20 |
+
"position": 0.09369222347935041,
|
| 21 |
+
"colour": 0.03420027456401537,
|
| 22 |
+
"scale": 0.0023372950294287876,
|
| 23 |
+
"rotation": 8.206806187445181e-05,
|
| 24 |
+
"opacity": 0.00015286443649529247,
|
| 25 |
+
"geometry": 0.0,
|
| 26 |
+
"loss": 0.5840554296970367,
|
| 27 |
+
"occupancy_iou": 0.30700542802611985
|
| 28 |
+
},
|
| 29 |
+
"checks": {
|
| 30 |
+
"validation_loss_improved": true,
|
| 31 |
+
"test_loss_improved": true,
|
| 32 |
+
"test_occupancy_iou_improved": true,
|
| 33 |
+
"test_occupancy_iou_at_least_005": true
|
| 34 |
+
},
|
| 35 |
+
"passed": true,
|
| 36 |
+
"scope": "Rendered mesh-proxy evaluation only; does not establish real-photo or mesh reconstruction quality",
|
| 37 |
+
"published_model_sha256": "83c065d2a50cf086928542cf8d40dc4416b379e38b9aa61d842dc9106d4b3306"
|
| 38 |
+
}
|
licenses/Idol-APACHE-2.0.txt
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
Apache License
|
| 3 |
+
Version 2.0, January 2004
|
| 4 |
+
http://www.apache.org/licenses/
|
| 5 |
+
|
| 6 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
| 7 |
+
|
| 8 |
+
1. Definitions.
|
| 9 |
+
|
| 10 |
+
"License" shall mean the terms and conditions for use, reproduction,
|
| 11 |
+
and distribution as defined by Sections 1 through 9 of this document.
|
| 12 |
+
|
| 13 |
+
"Licensor" shall mean the copyright owner or entity authorized by
|
| 14 |
+
the copyright owner that is granting the License.
|
| 15 |
+
|
| 16 |
+
"Legal Entity" shall mean the union of the acting entity and all
|
| 17 |
+
other entities that control, are controlled by, or are under common
|
| 18 |
+
control with that entity. For the purposes of this definition,
|
| 19 |
+
"control" means (i) the power, direct or indirect, to cause the
|
| 20 |
+
direction or management of such entity, whether by contract or
|
| 21 |
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
| 22 |
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
| 23 |
+
|
| 24 |
+
"You" (or "Your") shall mean an individual or Legal Entity
|
| 25 |
+
exercising permissions granted by this License.
|
| 26 |
+
|
| 27 |
+
"Source" form shall mean the preferred form for making modifications,
|
| 28 |
+
including but not limited to software source code, documentation
|
| 29 |
+
source, and configuration files.
|
| 30 |
+
|
| 31 |
+
"Object" form shall mean any form resulting from mechanical
|
| 32 |
+
transformation or translation of a Source form, including but
|
| 33 |
+
not limited to compiled object code, generated documentation,
|
| 34 |
+
and conversions to other media types.
|
| 35 |
+
|
| 36 |
+
"Work" shall mean the work of authorship, whether in Source or
|
| 37 |
+
Object form, made available under the License, as indicated by a
|
| 38 |
+
copyright notice that is included in or attached to the work
|
| 39 |
+
(an example is provided in the Appendix below).
|
| 40 |
+
|
| 41 |
+
"Derivative Works" shall mean any work, whether in Source or Object
|
| 42 |
+
form, that is based on (or derived from) the Work and for which the
|
| 43 |
+
editorial revisions, annotations, elaborations, or other modifications
|
| 44 |
+
represent, as a whole, an original work of authorship. For the purposes
|
| 45 |
+
of this License, Derivative Works shall not include works that remain
|
| 46 |
+
separable from, or merely link (or bind by name) to the interfaces of,
|
| 47 |
+
the Work and Derivative Works thereof.
|
| 48 |
+
|
| 49 |
+
"Contribution" shall mean any work of authorship, including
|
| 50 |
+
the original version of the Work and any modifications or additions
|
| 51 |
+
to that Work or Derivative Works thereof, that is intentionally
|
| 52 |
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
| 53 |
+
or by an individual or Legal Entity authorized to submit on behalf of
|
| 54 |
+
the copyright owner. For the purposes of this definition, "submitted"
|
| 55 |
+
means any form of electronic, verbal, or written communication sent
|
| 56 |
+
to the Licensor or its representatives, including but not limited to
|
| 57 |
+
communication on electronic mailing lists, source code control systems,
|
| 58 |
+
and issue tracking systems that are managed by, or on behalf of, the
|
| 59 |
+
Licensor for the purpose of discussing and improving the Work, but
|
| 60 |
+
excluding communication that is conspicuously marked or otherwise
|
| 61 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
| 62 |
+
|
| 63 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
| 64 |
+
on behalf of whom a Contribution has been received by Licensor and
|
| 65 |
+
subsequently incorporated within the Work.
|
| 66 |
+
|
| 67 |
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
| 68 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 69 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 70 |
+
copyright license to reproduce, prepare Derivative Works of,
|
| 71 |
+
publicly display, publicly perform, sublicense, and distribute the
|
| 72 |
+
Work and such Derivative Works in Source or Object form.
|
| 73 |
+
|
| 74 |
+
3. Grant of Patent License. Subject to the terms and conditions of
|
| 75 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 76 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 77 |
+
(except as stated in this section) patent license to make, have made,
|
| 78 |
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
| 79 |
+
where such license applies only to those patent claims licensable
|
| 80 |
+
by such Contributor that are necessarily infringed by their
|
| 81 |
+
Contribution(s) alone or by combination of their Contribution(s)
|
| 82 |
+
with the Work to which such Contribution(s) was submitted. If You
|
| 83 |
+
institute patent litigation against any entity (including a
|
| 84 |
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
| 85 |
+
or a Contribution incorporated within the Work constitutes direct
|
| 86 |
+
or contributory patent infringement, then any patent licenses
|
| 87 |
+
granted to You under this License for that Work shall terminate
|
| 88 |
+
as of the date such litigation is filed.
|
| 89 |
+
|
| 90 |
+
4. Redistribution. You may reproduce and distribute copies of the
|
| 91 |
+
Work or Derivative Works thereof in any medium, with or without
|
| 92 |
+
modifications, and in Source or Object form, provided that You
|
| 93 |
+
meet the following conditions:
|
| 94 |
+
|
| 95 |
+
(a) You must give any other recipients of the Work or
|
| 96 |
+
Derivative Works a copy of this License; and
|
| 97 |
+
|
| 98 |
+
(b) You must cause any modified files to carry prominent notices
|
| 99 |
+
stating that You changed the files; and
|
| 100 |
+
|
| 101 |
+
(c) You must retain, in the Source form of any Derivative Works
|
| 102 |
+
that You distribute, all copyright, patent, trademark, and
|
| 103 |
+
attribution notices from the Source form of the Work,
|
| 104 |
+
excluding those notices that do not pertain to any part of
|
| 105 |
+
the Derivative Works; and
|
| 106 |
+
|
| 107 |
+
(d) If the Work includes a "NOTICE" text file as part of its
|
| 108 |
+
distribution, then any Derivative Works that You distribute must
|
| 109 |
+
include a readable copy of the attribution notices contained
|
| 110 |
+
within such NOTICE file, excluding those notices that do not
|
| 111 |
+
pertain to any part of the Derivative Works, in at least one
|
| 112 |
+
of the following places: within a NOTICE text file distributed
|
| 113 |
+
as part of the Derivative Works; within the Source form or
|
| 114 |
+
documentation, if provided along with the Derivative Works; or,
|
| 115 |
+
within a display generated by the Derivative Works, if and
|
| 116 |
+
wherever such third-party notices normally appear. The contents
|
| 117 |
+
of the NOTICE file are for informational purposes only and
|
| 118 |
+
do not modify the License. You may add Your own attribution
|
| 119 |
+
notices within Derivative Works that You distribute, alongside
|
| 120 |
+
or as an addendum to the NOTICE text from the Work, provided
|
| 121 |
+
that such additional attribution notices cannot be construed
|
| 122 |
+
as modifying the License.
|
| 123 |
+
|
| 124 |
+
You may add Your own copyright statement to Your modifications and
|
| 125 |
+
may provide additional or different license terms and conditions
|
| 126 |
+
for use, reproduction, or distribution of Your modifications, or
|
| 127 |
+
for any such Derivative Works as a whole, provided Your use,
|
| 128 |
+
reproduction, and distribution of the Work otherwise complies with
|
| 129 |
+
the conditions stated in this License.
|
| 130 |
+
|
| 131 |
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
| 132 |
+
any Contribution intentionally submitted for inclusion in the Work
|
| 133 |
+
by You to the Licensor shall be under the terms and conditions of
|
| 134 |
+
this License, without any additional terms or conditions.
|
| 135 |
+
Notwithstanding the above, nothing herein shall supersede or modify
|
| 136 |
+
the terms of any separate license agreement you may have executed
|
| 137 |
+
with Licensor regarding such Contributions.
|
| 138 |
+
|
| 139 |
+
6. Trademarks. This License does not grant permission to use the trade
|
| 140 |
+
names, trademarks, service marks, or product names of the Licensor,
|
| 141 |
+
except as required for reasonable and customary use in describing the
|
| 142 |
+
origin of the Work and reproducing the content of the NOTICE file.
|
| 143 |
+
|
| 144 |
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
| 145 |
+
agreed to in writing, Licensor provides the Work (and each
|
| 146 |
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
| 147 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
| 148 |
+
implied, including, without limitation, any warranties or conditions
|
| 149 |
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
| 150 |
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
| 151 |
+
appropriateness of using or redistributing the Work and assume any
|
| 152 |
+
risks associated with Your exercise of permissions under this License.
|
| 153 |
+
|
| 154 |
+
8. Limitation of Liability. In no event and under no legal theory,
|
| 155 |
+
whether in tort (including negligence), contract, or otherwise,
|
| 156 |
+
unless required by applicable law (such as deliberate and grossly
|
| 157 |
+
negligent acts) or agreed to in writing, shall any Contributor be
|
| 158 |
+
liable to You for damages, including any direct, indirect, special,
|
| 159 |
+
incidental, or consequential damages of any character arising as a
|
| 160 |
+
result of this License or out of the use or inability to use the
|
| 161 |
+
Work (including but not limited to damages for loss of goodwill,
|
| 162 |
+
work stoppage, computer failure or malfunction, or any and all
|
| 163 |
+
other commercial damages or losses), even if such Contributor
|
| 164 |
+
has been advised of the possibility of such damages.
|
| 165 |
+
|
| 166 |
+
9. Accepting Warranty or Additional Liability. While redistributing
|
| 167 |
+
the Work or Derivative Works thereof, You may choose to offer,
|
| 168 |
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
| 169 |
+
or other liability obligations and/or rights consistent with this
|
| 170 |
+
License. However, in accepting such obligations, You may act only
|
| 171 |
+
on Your own behalf and on Your sole responsibility, not on behalf
|
| 172 |
+
of any other Contributor, and only if You agree to indemnify,
|
| 173 |
+
defend, and hold each Contributor harmless for any liability
|
| 174 |
+
incurred by, or claims asserted against, such Contributor by reason
|
| 175 |
+
of your accepting any such warranty or additional liability.
|
| 176 |
+
|
| 177 |
+
END OF TERMS AND CONDITIONS
|
| 178 |
+
|
| 179 |
+
APPENDIX: How to apply the Apache License to your work.
|
| 180 |
+
|
| 181 |
+
To apply the Apache License to your work, attach the following
|
| 182 |
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
| 183 |
+
replaced with your own identifying information. (Don't include
|
| 184 |
+
the brackets!) The text should be enclosed in the appropriate
|
| 185 |
+
comment syntax for the file format. We also recommend that a
|
| 186 |
+
file or class name and description of purpose be included on the
|
| 187 |
+
same "printed page" as the copyright notice for easier
|
| 188 |
+
identification within third-party archives.
|
| 189 |
+
|
| 190 |
+
Copyright [yyyy] [name of copyright owner]
|
| 191 |
+
|
| 192 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 193 |
+
you may not use this file except in compliance with the License.
|
| 194 |
+
You may obtain a copy of the License at
|
| 195 |
+
|
| 196 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
| 197 |
+
|
| 198 |
+
Unless required by applicable law or agreed to in writing, software
|
| 199 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 200 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 201 |
+
See the License for the specific language governing permissions and
|
| 202 |
+
limitations under the License.
|
model.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:83c065d2a50cf086928542cf8d40dc4416b379e38b9aa61d842dc9106d4b3306
|
| 3 |
+
size 1735755
|
pyproject.toml
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[build-system]
|
| 2 |
+
requires = ["setuptools>=77"]
|
| 3 |
+
build-backend = "setuptools.build_meta"
|
| 4 |
+
|
| 5 |
+
[project]
|
| 6 |
+
name = "forma3d-tiny"
|
| 7 |
+
version = "0.2.0"
|
| 8 |
+
license = "Apache-2.0"
|
| 9 |
+
license-files = ["LICENSE", "NOTICE", "THIRD_PARTY.md", "licenses/*.txt"]
|
| 10 |
+
readme = "README.md"
|
| 11 |
+
authors = [{name = "Lucasgitguy-co"}]
|
| 12 |
+
description = "Experimental local image-to-Gaussian student with cached teacher supervision"
|
| 13 |
+
requires-python = ">=3.11,<3.14"
|
| 14 |
+
dependencies = ["torch>=2.5", "numpy>=1.26", "pillow>=10", "plyfile>=1", "trimesh>=4", "scipy>=1.11"]
|
| 15 |
+
|
| 16 |
+
[project.optional-dependencies]
|
| 17 |
+
test = ["pytest>=8"]
|
| 18 |
+
data = ["huggingface_hub>=0.34", "pyarrow>=17"]
|
| 19 |
+
teacher = ["idol @ git+https://github.com/speridlabs/idol-sdk.git@4702a7f00850e34b6e83a2170cc123c3e9570744"]
|
| 20 |
+
|
| 21 |
+
[project.scripts]
|
| 22 |
+
image3d = "image3d_student.cli:main"
|
| 23 |
+
|
| 24 |
+
[tool.setuptools.packages.find]
|
| 25 |
+
where = ["src"]
|
| 26 |
+
|
| 27 |
+
[tool.pytest.ini_options]
|
| 28 |
+
testpaths = ["tests"]
|
requirements-tested-macos.txt
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
anyio==4.16.0
|
| 2 |
+
click==8.5.0
|
| 3 |
+
filelock==4.2.7
|
| 4 |
+
fsspec==2026.9.0
|
| 5 |
+
h11==0.16.0
|
| 6 |
+
hf-xet==1.8.0
|
| 7 |
+
httpcore2==2.16.0
|
| 8 |
+
httpx2==2.16.0
|
| 9 |
+
huggingface-hub==2.4.0
|
| 10 |
+
idna==3.20
|
| 11 |
+
iniconfig==2.3.1
|
| 12 |
+
jinja2==3.1.6
|
| 13 |
+
markupsafe==3.0.4
|
| 14 |
+
mpmath==1.3.0
|
| 15 |
+
networkx==3.6.1
|
| 16 |
+
numpy==2.4.6
|
| 17 |
+
packaging==26.3
|
| 18 |
+
pillow==13.0.0
|
| 19 |
+
pluggy==1.7.0
|
| 20 |
+
plyfile==1.1.5
|
| 21 |
+
pyarrow==26.0.0
|
| 22 |
+
pygments==2.21.0
|
| 23 |
+
pytest==9.2.0
|
| 24 |
+
pyyaml==6.0.3
|
| 25 |
+
scipy==1.17.1
|
| 26 |
+
setuptools==84.2.1
|
| 27 |
+
sympy==1.14.0
|
| 28 |
+
torch==2.15.0
|
| 29 |
+
tqdm==4.70.1
|
| 30 |
+
trimesh==5.2.0
|
| 31 |
+
truststore==0.10.5
|
| 32 |
+
typing-extensions==4.16.0
|
scripts/prepare_hf.py
ADDED
|
@@ -0,0 +1,463 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Prepare paired, canonical rendered images and coarse Gaussian targets.
|
| 2 |
+
|
| 3 |
+
These are mesh-derived proxy targets, NOT pretrained-teacher outputs or photos.
|
| 4 |
+
Only public, explicitly allowed assets are downloaded. Source meshes stay local.
|
| 5 |
+
"""
|
| 6 |
+
import argparse
|
| 7 |
+
import gzip
|
| 8 |
+
import hashlib
|
| 9 |
+
import json
|
| 10 |
+
import random
|
| 11 |
+
import shutil
|
| 12 |
+
import time
|
| 13 |
+
import urllib.error
|
| 14 |
+
import urllib.request
|
| 15 |
+
from pathlib import Path, PurePosixPath
|
| 16 |
+
|
| 17 |
+
import numpy as np
|
| 18 |
+
import pyarrow.parquet as pq
|
| 19 |
+
import trimesh
|
| 20 |
+
from huggingface_hub import hf_hub_download
|
| 21 |
+
|
| 22 |
+
from image3d_student.data import cache_sample, splat_targets
|
| 23 |
+
from image3d_student.splats import Splats, preview
|
| 24 |
+
from image3d_student.engine import split_rows
|
| 25 |
+
|
| 26 |
+
SCENARIO = ("scenario-labs/3d-collection", "55b4c002b4c1529fc48da3dff98516c3069bfa3f")
|
| 27 |
+
OBJAVERSE = ("allenai/objaverse", "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8")
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def digest(path):
|
| 31 |
+
h = hashlib.sha256()
|
| 32 |
+
with Path(path).open("rb") as f:
|
| 33 |
+
for block in iter(lambda: f.read(1024 * 1024), b""):
|
| 34 |
+
h.update(block)
|
| 35 |
+
return h.hexdigest()
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
class Downloader:
|
| 39 |
+
def __init__(self, root, max_file_mb, max_total_mb, reserve_gb):
|
| 40 |
+
self.root = Path(root)
|
| 41 |
+
self.root.mkdir(parents=True, exist_ok=True)
|
| 42 |
+
self.max_file = int(max_file_mb * 1024**2)
|
| 43 |
+
self.max_total = int(max_total_mb * 1024**2)
|
| 44 |
+
self.reserve = int(reserve_gb * 1024**3)
|
| 45 |
+
self.total = 0
|
| 46 |
+
|
| 47 |
+
def get(self, repo, revision, filename, expected=None):
|
| 48 |
+
parts = PurePosixPath(filename)
|
| 49 |
+
if parts.is_absolute() or ".." in parts.parts or not filename.endswith(".glb"):
|
| 50 |
+
raise ValueError("Only relative GLB paths are allowed")
|
| 51 |
+
out = self.root / repo.replace("/", "--") / revision / filename
|
| 52 |
+
if out.exists():
|
| 53 |
+
if expected and digest(out) != expected:
|
| 54 |
+
raise ValueError("Cached source checksum mismatch")
|
| 55 |
+
if out.stat().st_size > self.max_file:
|
| 56 |
+
raise ValueError("Cached asset exceeds per-file limit")
|
| 57 |
+
return out
|
| 58 |
+
if self.total >= self.max_total:
|
| 59 |
+
raise RuntimeError("Download budget exhausted")
|
| 60 |
+
out.parent.mkdir(parents=True, exist_ok=True)
|
| 61 |
+
url = f"https://huggingface.co/datasets/{repo}/resolve/{revision}/{filename}"
|
| 62 |
+
for attempt in range(4):
|
| 63 |
+
tmp = out.with_suffix(".part")
|
| 64 |
+
try:
|
| 65 |
+
# Public URL only: credentials are never forwarded to asset hosts.
|
| 66 |
+
with urllib.request.urlopen(url, timeout=60) as response, tmp.open("wb") as f:
|
| 67 |
+
length = int(response.headers.get("Content-Length", 0))
|
| 68 |
+
if length > self.max_file:
|
| 69 |
+
raise ValueError("Asset exceeds per-file limit")
|
| 70 |
+
count = 0
|
| 71 |
+
while block := response.read(1024 * 1024):
|
| 72 |
+
count += len(block)
|
| 73 |
+
self.total += len(block)
|
| 74 |
+
if count > self.max_file:
|
| 75 |
+
raise ValueError("Asset exceeds per-file limit")
|
| 76 |
+
if self.total > self.max_total:
|
| 77 |
+
raise RuntimeError("Download budget exhausted")
|
| 78 |
+
if shutil.disk_usage(self.root).free < self.reserve + len(block):
|
| 79 |
+
raise RuntimeError("Free disk space below reserve")
|
| 80 |
+
f.write(block)
|
| 81 |
+
if expected and digest(tmp) != expected:
|
| 82 |
+
raise ValueError("Source checksum mismatch")
|
| 83 |
+
tmp.replace(out)
|
| 84 |
+
return out
|
| 85 |
+
except urllib.error.HTTPError as exc:
|
| 86 |
+
if exc.code not in (429, 500, 502, 503, 504) or attempt == 3:
|
| 87 |
+
raise
|
| 88 |
+
time.sleep(min(2**attempt, 8))
|
| 89 |
+
finally:
|
| 90 |
+
tmp.unlink(missing_ok=True)
|
| 91 |
+
raise RuntimeError("Download retries exhausted")
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def scenario_candidates(cache, seed):
|
| 95 |
+
repo, revision = SCENARIO
|
| 96 |
+
path = hf_hub_download(repo, "data/train-00000-of-00001.parquet", repo_type="dataset",
|
| 97 |
+
revision=revision, local_dir=Path(cache) / "metadata/scenario")
|
| 98 |
+
rows = pq.read_table(path, columns=["id", "license", "model", "inputs", "outputs"]).to_pylist()
|
| 99 |
+
# Connected components keep alternate meshes generated from shared inputs together.
|
| 100 |
+
parent = {}
|
| 101 |
+
|
| 102 |
+
def find(x):
|
| 103 |
+
parent.setdefault(x, x)
|
| 104 |
+
if parent[x] != x:
|
| 105 |
+
parent[x] = find(parent[x])
|
| 106 |
+
return parent[x]
|
| 107 |
+
|
| 108 |
+
candidates = []
|
| 109 |
+
for row in rows:
|
| 110 |
+
if row["license"] != "cc-by-4.0" or "hunyuan" in (row["model"] or "").lower():
|
| 111 |
+
continue
|
| 112 |
+
assets = (row.get("inputs") or {}).get("assets") or []
|
| 113 |
+
keys = ["input:" + (a.get("sha256") or a["path"]) for a in assets if a.get("sha256") or a.get("path")]
|
| 114 |
+
keys += ["output:" + o["sha256"] for o in row["outputs"] if o.get("sha256")]
|
| 115 |
+
keys += [row["id"]]
|
| 116 |
+
for key in keys[1:]:
|
| 117 |
+
parent[find(key)] = find(keys[0])
|
| 118 |
+
for output in row["outputs"]:
|
| 119 |
+
if output.get("format") == "glb":
|
| 120 |
+
candidates.append({"repo": repo, "revision": revision, "path": output["path"],
|
| 121 |
+
"sha256": output.get("sha256"), "asset_id": row["id"], "license": "cc-by-4.0",
|
| 122 |
+
"author": "Scenario", "title": row["id"], "source_model": row["model"],
|
| 123 |
+
"source_url": f"https://huggingface.co/datasets/{repo}", "group_key": keys[0]})
|
| 124 |
+
break
|
| 125 |
+
for row in candidates:
|
| 126 |
+
row["object_id"] = "scenario-" + hashlib.sha256(find(row.pop("group_key")).encode()).hexdigest()[:20]
|
| 127 |
+
candidates.sort(key=lambda r: r["asset_id"])
|
| 128 |
+
random.Random(seed).shuffle(candidates)
|
| 129 |
+
return candidates
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
def objaverse_candidates(cache, seed, shards):
|
| 133 |
+
repo, revision = OBJAVERSE
|
| 134 |
+
candidates = []
|
| 135 |
+
for shard in range(shards):
|
| 136 |
+
part = f"000-{shard:03d}"
|
| 137 |
+
path = hf_hub_download(repo, f"metadata/{part}.json.gz", repo_type="dataset", revision=revision,
|
| 138 |
+
local_dir=Path(cache) / "metadata/objaverse")
|
| 139 |
+
with gzip.open(path) as f:
|
| 140 |
+
records = json.load(f)
|
| 141 |
+
for uid, row in records.items():
|
| 142 |
+
# Start with the more conservative CC0 subset; no NC/SA/unknown assets.
|
| 143 |
+
if row.get("license") != "cc0" or row.get("isAgeRestricted") or row.get("animationCount", 0):
|
| 144 |
+
continue
|
| 145 |
+
candidates.append({"repo": repo, "revision": revision, "path": f"glbs/{part}/{uid}.glb",
|
| 146 |
+
"asset_id": uid, "object_id": "objaverse-" + uid, "license": "cc0-1.0",
|
| 147 |
+
"author": row.get("user", {}).get("displayName", "Unknown"), "title": row.get("name", uid),
|
| 148 |
+
"source_url": row.get("viewerUrl", f"https://sketchfab.com/3d-models/{uid}")})
|
| 149 |
+
candidates.sort(key=lambda r: r["asset_id"])
|
| 150 |
+
random.Random(seed).shuffle(candidates)
|
| 151 |
+
return candidates
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
def mesh_splats(path, count, grid, seed):
|
| 155 |
+
scene = trimesh.load_scene(path, process=False)
|
| 156 |
+
meshes = []
|
| 157 |
+
for node in scene.graph.nodes_geometry:
|
| 158 |
+
matrix, name = scene.graph[node]
|
| 159 |
+
mesh = scene.geometry[name].copy()
|
| 160 |
+
if not isinstance(mesh, trimesh.Trimesh) or not len(mesh.faces):
|
| 161 |
+
continue
|
| 162 |
+
mesh.apply_transform(matrix)
|
| 163 |
+
meshes.append(mesh)
|
| 164 |
+
if not meshes or sum(len(m.faces) for m in meshes) > 500_000:
|
| 165 |
+
raise ValueError("Missing mesh or more than 500,000 triangles")
|
| 166 |
+
bounds = np.array([m.bounds for m in meshes])
|
| 167 |
+
low, high = bounds[:, 0].min(axis=0), bounds[:, 1].max(axis=0)
|
| 168 |
+
extent = float((high - low).max())
|
| 169 |
+
if not np.isfinite(bounds).all() or extent < 1e-8:
|
| 170 |
+
raise ValueError("Degenerate mesh")
|
| 171 |
+
center = (low + high) / 2
|
| 172 |
+
factor = .9 / extent
|
| 173 |
+
areas = np.array([m.area for m in meshes])
|
| 174 |
+
if not np.isfinite(areas).all() or areas.sum() <= 0:
|
| 175 |
+
raise ValueError("Invalid surface area")
|
| 176 |
+
counts = np.random.default_rng(seed).multinomial(count, areas / areas.sum())
|
| 177 |
+
points, colours = [], []
|
| 178 |
+
for mesh, n in zip(meshes, counts):
|
| 179 |
+
if not n:
|
| 180 |
+
continue
|
| 181 |
+
xyz, faces = trimesh.sample.sample_surface(mesh, int(n), seed=seed)
|
| 182 |
+
bary = trimesh.triangles.points_to_barycentric(mesh.triangles[faces], xyz)
|
| 183 |
+
vis = mesh.visual
|
| 184 |
+
if vis.kind == "texture" and vis.uv is not None:
|
| 185 |
+
uv = (vis.uv[mesh.faces[faces]] * bary[:, :, None]).sum(axis=1)
|
| 186 |
+
sampled = np.asarray(vis.material.to_color(uv))
|
| 187 |
+
if sampled.ndim == 0:
|
| 188 |
+
raise ValueError("Material has no usable texture or base colour")
|
| 189 |
+
# Untextured PBR materials can return one constant RGBA value.
|
| 190 |
+
if sampled.ndim == 1:
|
| 191 |
+
sampled = np.broadcast_to(sampled, (n, len(sampled)))
|
| 192 |
+
colour = sampled[:, :3] / 255.
|
| 193 |
+
elif vis.kind == "vertex":
|
| 194 |
+
colour = (vis.vertex_colors[mesh.faces[faces], :3] * bary[:, :, None]).sum(axis=1) / 255.
|
| 195 |
+
elif vis.kind == "face":
|
| 196 |
+
colour = vis.face_colors[faces, :3] / 255.
|
| 197 |
+
else:
|
| 198 |
+
colour = np.full((n, 3), .65)
|
| 199 |
+
points.append((xyz - center) * factor)
|
| 200 |
+
colours.append(colour)
|
| 201 |
+
xyz = np.concatenate(points).astype(np.float32)
|
| 202 |
+
rgb = np.concatenate(colours).astype(np.float32)
|
| 203 |
+
n = len(xyz)
|
| 204 |
+
splats = Splats(xyz, rgb, np.full((n, 3), .6 / grid),
|
| 205 |
+
np.tile([1, 0, 0, 0], (n, 1)), np.full((n, 1), .9))
|
| 206 |
+
transform = np.eye(4)
|
| 207 |
+
transform[:3, :3] *= factor
|
| 208 |
+
transform[:3, 3] = -center * factor
|
| 209 |
+
return splats, transform.tolist()
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
def save_progress(out, args, rows, provenance, failures):
|
| 213 |
+
state = {"version": 1, "settings": vars(args), "rows": rows,
|
| 214 |
+
"sources": provenance, "skipped": failures}
|
| 215 |
+
temporary = out / "progress.json.tmp"
|
| 216 |
+
temporary.write_text(json.dumps(state))
|
| 217 |
+
temporary.replace(out / "progress.json")
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
def check_resume_settings(previous, args):
|
| 221 |
+
for key in ("grid", "views", "surface_points", "seed", "scenario", "objaverse"):
|
| 222 |
+
if previous[key] != getattr(args, key):
|
| 223 |
+
raise ValueError(f"Cannot change {key} while resuming; use a new dataset directory")
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
def recover_legacy(out, args):
|
| 227 |
+
"""Recover the old writer's completed files without rendering or downloading.
|
| 228 |
+
|
| 229 |
+
Old runs saved sources and arrays, but lost manifest rows on insufficient
|
| 230 |
+
candidates. Recreate those rows and verify targets against cached GLBs.
|
| 231 |
+
"""
|
| 232 |
+
previous = json.loads((out / "preparation.json").read_text())["settings"]
|
| 233 |
+
check_resume_settings(previous, args)
|
| 234 |
+
provenance = json.loads((out / "sources.json").read_text())
|
| 235 |
+
failures = json.loads((out / "skipped.json").read_text())
|
| 236 |
+
rows = []
|
| 237 |
+
for index, item in enumerate(provenance):
|
| 238 |
+
path = Path(args.cache) / item["repo"].replace("/", "--") / item["revision"] / item["path"]
|
| 239 |
+
if not path.is_file() or digest(path) != item["sha256"]:
|
| 240 |
+
raise ValueError(f"Missing or corrupt cached source for {item['asset_id']}")
|
| 241 |
+
splats, transform = mesh_splats(path, args.surface_points, args.grid,
|
| 242 |
+
int(item["sha256"][:8], 16) ^ args.seed)
|
| 243 |
+
stem = hashlib.sha256((item["repo"] + item["asset_id"]).encode()).hexdigest()[:20]
|
| 244 |
+
for view in range(args.views):
|
| 245 |
+
sample_id = f"{stem}-v{view}"
|
| 246 |
+
image, target = f"images/{sample_id}.png", f"targets/{sample_id}.npz"
|
| 247 |
+
yaw = 2 * np.pi * view / args.views
|
| 248 |
+
c, s = np.cos(yaw), np.sin(yaw)
|
| 249 |
+
rotation = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]], np.float32)
|
| 250 |
+
rotated = Splats(splats.xyz @ rotation.T, splats.rgb, splats.scale, splats.quat, splats.opacity)
|
| 251 |
+
expected = splat_targets(rotated, args.grid)
|
| 252 |
+
with np.load(out / target, allow_pickle=False) as cached:
|
| 253 |
+
if set(cached.files) != set(expected):
|
| 254 |
+
raise ValueError(f"Target fields differ for {sample_id}")
|
| 255 |
+
for key, value in expected.items():
|
| 256 |
+
if not np.array_equal(cached[key], value):
|
| 257 |
+
raise ValueError(f"Recovered target differs for {sample_id}: {key}")
|
| 258 |
+
from PIL import Image
|
| 259 |
+
with Image.open(out / image) as check:
|
| 260 |
+
check.verify()
|
| 261 |
+
rows.append({"id": sample_id, "image": image, "target": target,
|
| 262 |
+
"source": "mesh-proxy:" + item["repo"], "grid": args.grid,
|
| 263 |
+
"teachers": {"appearance": "mesh-proxy:" + item["repo"], "coarse": None, "fine": None},
|
| 264 |
+
"teacher_gaussians": len(splats.xyz), "retained_gaussians": int(expected["occ"].sum()),
|
| 265 |
+
"geometry_transforms": {"coarse": None, "fine": None},
|
| 266 |
+
"image_sha256": digest(out / image), "target_sha256": digest(out / target),
|
| 267 |
+
"metadata": {**item, "normalization_matrix": transform, "yaw_radians": float(yaw),
|
| 268 |
+
"render": "orthographic Gaussian proxy, camera +z",
|
| 269 |
+
"target": "isotropic surface-sampled mesh proxy; not a pretrained teacher"}})
|
| 270 |
+
if (index + 1) % 10 == 0 or index + 1 == len(provenance):
|
| 271 |
+
print(json.dumps({"recovered_objects": index + 1, "existing_objects": len(provenance)}), flush=True)
|
| 272 |
+
save_progress(out, args, rows, provenance, failures)
|
| 273 |
+
return rows, provenance, failures
|
| 274 |
+
|
| 275 |
+
|
| 276 |
+
def load_progress(out, args):
|
| 277 |
+
if not (out / "progress.json").exists():
|
| 278 |
+
return recover_legacy(out, args)
|
| 279 |
+
state = json.loads((out / "progress.json").read_text())
|
| 280 |
+
if state.get("version") != 1:
|
| 281 |
+
raise ValueError("Unsupported preparation progress version")
|
| 282 |
+
check_resume_settings(state["settings"], args)
|
| 283 |
+
for row in state["rows"]:
|
| 284 |
+
for key in ("image", "target"):
|
| 285 |
+
path = (out / row[key]).resolve()
|
| 286 |
+
if not path.is_relative_to(out.resolve()) or digest(path) != row[key + "_sha256"]:
|
| 287 |
+
raise ValueError(f"Prepared file checksum mismatch: {row['id']} {key}")
|
| 288 |
+
return state["rows"], state["sources"], state["skipped"]
|
| 289 |
+
|
| 290 |
+
|
| 291 |
+
def prune_invisible(out, rows, provenance, failures):
|
| 292 |
+
from PIL import Image
|
| 293 |
+
bad = set()
|
| 294 |
+
for row in rows:
|
| 295 |
+
with Image.open(out / row["image"]) as image:
|
| 296 |
+
if image.convert("RGB").getbbox() is None:
|
| 297 |
+
bad.add((row["metadata"]["repo"], row["metadata"]["asset_id"]))
|
| 298 |
+
for repo, asset in sorted(bad):
|
| 299 |
+
failures.append({"repo": repo, "asset": asset,
|
| 300 |
+
"error": "Rendered view has no visible pixels", "terminal": True})
|
| 301 |
+
if bad:
|
| 302 |
+
print(json.dumps({"excluded_invisible_objects": len(bad), "existing_files_preserved": True}), flush=True)
|
| 303 |
+
return ([r for r in rows if (r["metadata"]["repo"], r["metadata"]["asset_id"]) not in bad],
|
| 304 |
+
[p for p in provenance if (p["repo"], p["asset_id"]) not in bad])
|
| 305 |
+
|
| 306 |
+
|
| 307 |
+
def group_duplicates(rows, provenance):
|
| 308 |
+
"""Link entire objects when any views or target files are byte-identical."""
|
| 309 |
+
parent = {}
|
| 310 |
+
def find(x):
|
| 311 |
+
parent.setdefault(x, x)
|
| 312 |
+
if parent[x] != x:
|
| 313 |
+
parent[x] = find(parent[x])
|
| 314 |
+
return parent[x]
|
| 315 |
+
hashes = {}
|
| 316 |
+
for row in rows:
|
| 317 |
+
meta = row["metadata"]
|
| 318 |
+
original = meta.setdefault("source_object_id", meta["object_id"])
|
| 319 |
+
find(original)
|
| 320 |
+
for field in ("image_sha256", "target_sha256"):
|
| 321 |
+
key = (field, row[field])
|
| 322 |
+
if key in hashes:
|
| 323 |
+
a, b = find(original), find(hashes[key])
|
| 324 |
+
parent[max(a, b)] = min(a, b)
|
| 325 |
+
else:
|
| 326 |
+
hashes[key] = original
|
| 327 |
+
for row in rows:
|
| 328 |
+
row["metadata"]["object_id"] = find(row["metadata"]["source_object_id"])
|
| 329 |
+
for item in provenance:
|
| 330 |
+
original = item.setdefault("source_object_id", item["object_id"])
|
| 331 |
+
item["object_id"] = find(original)
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
def prepare(args):
|
| 335 |
+
out = Path(args.out)
|
| 336 |
+
occupied = out.exists() and any(out.iterdir())
|
| 337 |
+
if occupied and not getattr(args, "resume", False):
|
| 338 |
+
raise ValueError("Output is not empty. Use --resume to retain completed objects.")
|
| 339 |
+
if args.scenario + args.objaverse < 4:
|
| 340 |
+
raise ValueError("Request at least four objects")
|
| 341 |
+
out.mkdir(parents=True, exist_ok=True)
|
| 342 |
+
if occupied:
|
| 343 |
+
all_rows, provenance, failures = load_progress(out, args)
|
| 344 |
+
else:
|
| 345 |
+
all_rows, provenance, failures = [], [], []
|
| 346 |
+
save_progress(out, args, all_rows, provenance, failures)
|
| 347 |
+
all_rows, provenance = prune_invisible(out, all_rows, provenance, failures)
|
| 348 |
+
save_progress(out, args, all_rows, provenance, failures)
|
| 349 |
+
seen = {item["sha256"] for item in provenance}
|
| 350 |
+
completed = {(item["repo"], item["asset_id"]) for item in provenance}
|
| 351 |
+
rejected = {(f["repo"], f["asset"]) for f in failures if f.get("terminal")}
|
| 352 |
+
counts = {}
|
| 353 |
+
fetch = Downloader(args.cache, args.max_file_mb, args.max_download_mb, args.reserve_gb)
|
| 354 |
+
sources = []
|
| 355 |
+
if args.scenario:
|
| 356 |
+
ready = sum(item["repo"] == SCENARIO[0] for item in provenance)
|
| 357 |
+
candidates = scenario_candidates(args.cache, args.seed) if ready < args.scenario else []
|
| 358 |
+
sources.append((SCENARIO[0], candidates, args.scenario, ready))
|
| 359 |
+
if args.objaverse:
|
| 360 |
+
ready = sum(item["repo"] == OBJAVERSE[0] for item in provenance)
|
| 361 |
+
candidates = objaverse_candidates(args.cache, args.seed, args.objaverse_shards) if ready < args.objaverse else []
|
| 362 |
+
sources.append((OBJAVERSE[0], candidates, args.objaverse, ready))
|
| 363 |
+
for repo, candidates, wanted, accepted in sources:
|
| 364 |
+
for item in candidates:
|
| 365 |
+
if accepted >= wanted:
|
| 366 |
+
break
|
| 367 |
+
if (item["repo"], item["asset_id"]) in completed | rejected:
|
| 368 |
+
continue
|
| 369 |
+
staging = out / "_staging"
|
| 370 |
+
try:
|
| 371 |
+
path = fetch.get(item["repo"], item["revision"], item["path"], item.get("sha256"))
|
| 372 |
+
checksum = digest(path)
|
| 373 |
+
if checksum in seen:
|
| 374 |
+
continue
|
| 375 |
+
item["sha256"] = checksum
|
| 376 |
+
item_seed = int(checksum[:8], 16) ^ args.seed
|
| 377 |
+
splats, transform = mesh_splats(path, args.surface_points, args.grid, item_seed)
|
| 378 |
+
stem = hashlib.sha256((item["repo"] + item["asset_id"]).encode()).hexdigest()[:20]
|
| 379 |
+
staging.mkdir(parents=True, exist_ok=True)
|
| 380 |
+
rows = []
|
| 381 |
+
for view in range(args.views):
|
| 382 |
+
yaw = 2 * np.pi * view / args.views
|
| 383 |
+
c, s = np.cos(yaw), np.sin(yaw)
|
| 384 |
+
rotation = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]], np.float32)
|
| 385 |
+
rotated = Splats(splats.xyz @ rotation.T, splats.rgb, splats.scale, splats.quat, splats.opacity)
|
| 386 |
+
image = staging / "input.png"
|
| 387 |
+
rendered = preview(rotated, size=128)
|
| 388 |
+
if rendered.getbbox() is None:
|
| 389 |
+
raise ValueError("Rendered view has no visible pixels")
|
| 390 |
+
rendered.save(image)
|
| 391 |
+
metadata = {**item, "object_id": item["object_id"], "normalization_matrix": transform,
|
| 392 |
+
"yaw_radians": float(yaw), "render": "orthographic Gaussian proxy, camera +z",
|
| 393 |
+
"target": "isotropic surface-sampled mesh proxy; not a pretrained teacher"}
|
| 394 |
+
rows.append(cache_sample(staging, f"{stem}-v{view}", image, rotated, args.grid,
|
| 395 |
+
source="mesh-proxy:" + item["repo"], extra=metadata))
|
| 396 |
+
for folder in ("images", "targets"):
|
| 397 |
+
(out / folder).mkdir(exist_ok=True)
|
| 398 |
+
for file in (staging / folder).iterdir():
|
| 399 |
+
file.replace(out / folder / file.name)
|
| 400 |
+
all_rows.extend(rows)
|
| 401 |
+
seen.add(checksum)
|
| 402 |
+
provenance.append(item)
|
| 403 |
+
completed.add((item["repo"], item["asset_id"]))
|
| 404 |
+
accepted += 1
|
| 405 |
+
save_progress(out, args, all_rows, provenance, failures)
|
| 406 |
+
print(json.dumps({"repo": item["repo"], "accepted": accepted, "requested": wanted,
|
| 407 |
+
"asset": item["asset_id"]}), flush=True)
|
| 408 |
+
except RuntimeError:
|
| 409 |
+
raise # resource limits are a hard stop
|
| 410 |
+
except Exception as exc:
|
| 411 |
+
failures.append({"repo": item["repo"], "asset": item["asset_id"],
|
| 412 |
+
"error": type(exc).__name__ + ": " + str(exc)[:200],
|
| 413 |
+
"terminal": "no visible pixels" in str(exc)})
|
| 414 |
+
print(json.dumps({"skipped": item["asset_id"], "reason": failures[-1]["error"]}), flush=True)
|
| 415 |
+
finally:
|
| 416 |
+
shutil.rmtree(staging, ignore_errors=True)
|
| 417 |
+
counts[repo] = {"requested": wanted, "prepared": accepted}
|
| 418 |
+
group_duplicates(all_rows, provenance)
|
| 419 |
+
save_progress(out, args, all_rows, provenance, failures)
|
| 420 |
+
(out / "sources.json").write_text(json.dumps(provenance, indent=2))
|
| 421 |
+
(out / "skipped.json").write_text(json.dumps(failures, indent=2))
|
| 422 |
+
report = {"counts": counts, "samples": len(all_rows), "objects": len(provenance),
|
| 423 |
+
"distinct_groups": len({r["metadata"]["object_id"] for r in all_rows}),
|
| 424 |
+
"settings": vars(args), "rendered_proxy_data": True,
|
| 425 |
+
"excluded": ["scenario-labs/3d-collection-hunyuan", "3dlg-hcvc/MultiScan",
|
| 426 |
+
"huanngzh/3D-Front", "facebook/show3d-dataset", "Voxel51/gaussian_splatting"]}
|
| 427 |
+
(out / "preparation.json").write_text(json.dumps(report, indent=2))
|
| 428 |
+
if any(v["prepared"] < v["requested"] for v in counts.values()):
|
| 429 |
+
raise ValueError("Not enough eligible assets. Completed objects are saved. Rerun with --resume and a larger --objaverse-shards value.")
|
| 430 |
+
if report["distinct_groups"] < 4:
|
| 431 |
+
raise ValueError("Not enough independent object groups")
|
| 432 |
+
# The test partition never enters training or checkpoint selection.
|
| 433 |
+
development, test = split_rows(all_rows, .15, args.seed + 1)
|
| 434 |
+
for name, rows in [("manifest.jsonl", development), ("test-manifest.jsonl", test)]:
|
| 435 |
+
(out / name).write_text("".join(json.dumps(r) + "\n" for r in rows))
|
| 436 |
+
print(json.dumps(report, indent=2))
|
| 437 |
+
|
| 438 |
+
|
| 439 |
+
def main():
|
| 440 |
+
p = argparse.ArgumentParser(description=__doc__)
|
| 441 |
+
p.add_argument("--out", required=True)
|
| 442 |
+
p.add_argument("--cache", default="data/downloads")
|
| 443 |
+
p.add_argument("--scenario", type=int, default=64)
|
| 444 |
+
p.add_argument("--objaverse", type=int, default=32)
|
| 445 |
+
p.add_argument("--objaverse-shards", type=int, default=8)
|
| 446 |
+
p.add_argument("--resume", action="store_true", help="Reuse and verify completed objects, including older failed runs")
|
| 447 |
+
p.add_argument("--grid", type=int, choices=[8, 16, 32], default=16)
|
| 448 |
+
p.add_argument("--views", type=int, default=4)
|
| 449 |
+
p.add_argument("--surface-points", type=int, default=4096)
|
| 450 |
+
p.add_argument("--seed", type=int, default=42)
|
| 451 |
+
p.add_argument("--max-file-mb", type=int, default=16)
|
| 452 |
+
p.add_argument("--max-download-mb", type=int, default=2048)
|
| 453 |
+
p.add_argument("--reserve-gb", type=float, default=2)
|
| 454 |
+
args = p.parse_args()
|
| 455 |
+
if min(args.scenario, args.objaverse) < 0 or not 1 <= args.objaverse_shards <= 160:
|
| 456 |
+
p.error("Invalid object counts or shard count")
|
| 457 |
+
if min(args.views, args.surface_points, args.max_file_mb, args.max_download_mb, args.reserve_gb) <= 0:
|
| 458 |
+
p.error("Counts and limits must be positive")
|
| 459 |
+
prepare(args)
|
| 460 |
+
|
| 461 |
+
|
| 462 |
+
if __name__ == "__main__":
|
| 463 |
+
main()
|
scripts/release.py
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Evaluate a completed run, stage a self-contained release, optionally publish it."""
|
| 2 |
+
import argparse
|
| 3 |
+
import hashlib
|
| 4 |
+
import json
|
| 5 |
+
import shutil
|
| 6 |
+
from pathlib import Path
|
| 7 |
+
|
| 8 |
+
import torch
|
| 9 |
+
from torch.utils.data import DataLoader
|
| 10 |
+
|
| 11 |
+
from image3d_student.data import CachedDataset, load_manifest
|
| 12 |
+
from image3d_student.engine import device_for, evaluate, generate
|
| 13 |
+
from image3d_student.model import Student
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def sha(path):
|
| 17 |
+
return hashlib.sha256(Path(path).read_bytes()).hexdigest()
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def evaluate_release(args):
|
| 21 |
+
run, dataset = Path(args.run), Path(args.data)
|
| 22 |
+
meta = json.loads((run / "run.json").read_text())
|
| 23 |
+
checkpoint = torch.load(run / "best.pt", map_location="cpu", weights_only=True)
|
| 24 |
+
last = torch.load(run / "last.pt", map_location="cpu", weights_only=True)
|
| 25 |
+
if last["step"] != meta["steps_requested"]:
|
| 26 |
+
raise ValueError("Training did not complete the requested steps")
|
| 27 |
+
if checkpoint.get("step", 0) < 1 or not meta.get("initialization"):
|
| 28 |
+
raise ValueError("Expected completed post-training from a base checkpoint")
|
| 29 |
+
if sha(args.base) != meta["initialization"]["sha256"]:
|
| 30 |
+
raise ValueError("Base checkpoint differs from the training initialization")
|
| 31 |
+
if sha(dataset / "manifest.jsonl") != meta["manifest_sha256"]:
|
| 32 |
+
raise ValueError("Training manifest changed")
|
| 33 |
+
development = load_manifest(dataset / "manifest.jsonl")
|
| 34 |
+
test = load_manifest(dataset / "test-manifest.jsonl")
|
| 35 |
+
selected_ids = set(meta["train_ids"]) | set(meta["val_ids"])
|
| 36 |
+
if selected_ids != {r["id"] for r in development}:
|
| 37 |
+
raise ValueError("Run split does not match development manifest")
|
| 38 |
+
if {r["metadata"]["object_id"] for r in development} & {r["metadata"]["object_id"] for r in test}:
|
| 39 |
+
raise ValueError("Test object leakage")
|
| 40 |
+
for key in ["image_sha256", "target_sha256"]:
|
| 41 |
+
if {r[key] for r in development} & {r[key] for r in test}:
|
| 42 |
+
raise ValueError("Duplicate data across development and test")
|
| 43 |
+
device = device_for(args.device)
|
| 44 |
+
model = Student(**checkpoint["config"]).to(device)
|
| 45 |
+
model.load_state_dict(checkpoint["model"])
|
| 46 |
+
loader = DataLoader(CachedDataset(dataset / "test-manifest.jsonl"), batch_size=1)
|
| 47 |
+
final = evaluate(model, loader, device)
|
| 48 |
+
base = torch.load(args.base, map_location="cpu", weights_only=True)
|
| 49 |
+
initial = Student(**checkpoint["config"]).to(device)
|
| 50 |
+
result = initial.load_state_dict({k: v for k, v in base["model"].items() if k not in ("coords", "centers")}, strict=False)
|
| 51 |
+
if set(result.missing_keys) != {"coords", "centers"} or result.unexpected_keys:
|
| 52 |
+
raise ValueError("Base architecture mismatch")
|
| 53 |
+
baseline = evaluate(initial, loader, device)
|
| 54 |
+
best_validation = min(json.loads(line)["validation"]["loss"] for line in
|
| 55 |
+
(run / "metrics.jsonl").read_text().splitlines())
|
| 56 |
+
checks = {"validation_loss_improved": best_validation < meta["baseline_validation"]["loss"],
|
| 57 |
+
"test_loss_improved": final["loss"] < baseline["loss"],
|
| 58 |
+
"test_occupancy_iou_improved": final["occupancy_iou"] > baseline["occupancy_iou"],
|
| 59 |
+
"test_occupancy_iou_at_least_005": final["occupancy_iou"] >= .05}
|
| 60 |
+
report = {"checkpoint_sha256": sha(run / "best.pt"), "base_sha256": sha(args.base),
|
| 61 |
+
"test_manifest_sha256": sha(dataset / "test-manifest.jsonl"),
|
| 62 |
+
"test_objects": len({r["metadata"]["object_id"] for r in test}),
|
| 63 |
+
"test_samples": len(test), "baseline_test": baseline, "posttrained_test": final,
|
| 64 |
+
"checks": checks, "passed": all(checks.values()),
|
| 65 |
+
"scope": "Rendered mesh-proxy evaluation only; does not establish real-photo or mesh reconstruction quality"}
|
| 66 |
+
(run / "evaluation.json").write_text(json.dumps(report, indent=2))
|
| 67 |
+
print(json.dumps(report, indent=2), flush=True)
|
| 68 |
+
# Keep qualitative inspection files local; all held-out objects, first view.
|
| 69 |
+
example_dir = run / "inspection"
|
| 70 |
+
example_dir.mkdir(exist_ok=True)
|
| 71 |
+
seen = set()
|
| 72 |
+
from image3d_student.splats import preview, read_ply
|
| 73 |
+
from PIL import Image, ImageDraw
|
| 74 |
+
for row in test:
|
| 75 |
+
group = row["metadata"]["object_id"]
|
| 76 |
+
if group in seen:
|
| 77 |
+
continue
|
| 78 |
+
seen.add(group)
|
| 79 |
+
out = example_dir / (row["id"] + ".ply")
|
| 80 |
+
if not out.exists():
|
| 81 |
+
try:
|
| 82 |
+
generate(run / "best.pt", dataset / row["image"], out, args.device)
|
| 83 |
+
except ValueError as exc:
|
| 84 |
+
if "No occupied cells" not in str(exc):
|
| 85 |
+
raise
|
| 86 |
+
report["checks"]["nonempty_examples"] = False
|
| 87 |
+
report["passed"] = False
|
| 88 |
+
continue
|
| 89 |
+
sheet = Image.new("RGB", (512, 152), "black")
|
| 90 |
+
sheet.paste(Image.open(dataset / row["image"]).convert("RGB").resize((128, 128)), (0, 24))
|
| 91 |
+
splats = read_ply(out)
|
| 92 |
+
for i, angle in enumerate([0, 1.5707963, 3.1415927]):
|
| 93 |
+
sheet.paste(preview(splats, size=128, yaw=angle), (128 * (i + 1), 24))
|
| 94 |
+
ImageDraw.Draw(sheet).text((5, 5), "Input proxy | prediction front | side | back", fill="white")
|
| 95 |
+
sheet.save(out.with_suffix(".png"))
|
| 96 |
+
if len(seen) >= 8:
|
| 97 |
+
break
|
| 98 |
+
(run / "evaluation.json").write_text(json.dumps(report, indent=2))
|
| 99 |
+
if not report["passed"]:
|
| 100 |
+
raise ValueError("Evaluation gate failed. Nothing was published. Inspect evaluation.json and improve data/training.")
|
| 101 |
+
return checkpoint, meta, report
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
def stage(args, checkpoint, meta, report):
|
| 105 |
+
source = Path(__file__).resolve().parents[1]
|
| 106 |
+
release = Path(args.release)
|
| 107 |
+
if release.exists():
|
| 108 |
+
raise ValueError("Release directory already exists; choose a new --release path")
|
| 109 |
+
release.mkdir(parents=True)
|
| 110 |
+
shutil.copytree(source / "src", release / "src", ignore=shutil.ignore_patterns("__pycache__", "*.egg-info"))
|
| 111 |
+
shutil.copytree(source / "scripts", release / "scripts", ignore=shutil.ignore_patterns("__pycache__"))
|
| 112 |
+
shutil.copytree(source / "licenses", release / "licenses")
|
| 113 |
+
for filename in ["pyproject.toml", "LICENSE", "NOTICE", "THIRD_PARTY.md", "DATASETS.md", "COMMANDS.md", "setup-mac.sh", "train-mac.sh", "requirements-tested-macos.txt"]:
|
| 114 |
+
shutil.copyfile(source / filename, release / filename)
|
| 115 |
+
# Publish inference weights only; optimizer and local absolute paths stay local.
|
| 116 |
+
public_meta = {k: v for k, v in meta.items() if k != "dataset"}
|
| 117 |
+
torch.save({"format": 1, "config": checkpoint["config"], "model": checkpoint["model"],
|
| 118 |
+
"step": checkpoint["step"], "metadata": public_meta}, release / "model.pt")
|
| 119 |
+
(release / "config.json").write_text(json.dumps(checkpoint["config"], indent=2))
|
| 120 |
+
(release / "training.json").write_text(json.dumps(public_meta, indent=2))
|
| 121 |
+
(release / "evaluation.json").write_text(json.dumps({**report,
|
| 122 |
+
"published_model_sha256": sha(release / "model.pt")}, indent=2))
|
| 123 |
+
shutil.copyfile(Path(args.data) / "sources.json", release / "ATTRIBUTIONS.json")
|
| 124 |
+
used = sorted({r["repo"] for r in json.loads((release / "ATTRIBUTIONS.json").read_text())})
|
| 125 |
+
datasets_yaml = "\n".join("- " + repo for repo in used)
|
| 126 |
+
text = f'''---
|
| 127 |
+
license: apache-2.0
|
| 128 |
+
pipeline_tag: image-to-3d
|
| 129 |
+
base_model: Lucasgitguy-co/image3d-student
|
| 130 |
+
model_name: Forma3D-Tiny v0.2
|
| 131 |
+
datasets:
|
| 132 |
+
{datasets_yaml}
|
| 133 |
+
tags:
|
| 134 |
+
- pytorch
|
| 135 |
+
- gaussian-splatting
|
| 136 |
+
- research-prototype
|
| 137 |
+
- mesh-proxy-supervision
|
| 138 |
+
---
|
| 139 |
+
# Forma3D-Tiny v0.2
|
| 140 |
+
|
| 141 |
+
An experimental compact image-to-Gaussian model post-trained from Image3D Student's
|
| 142 |
+
synthetic demonstration checkpoint. This is a coarse research baseline, not a
|
| 143 |
+
general-purpose photo-to-3D model. Its grid is {checkpoint["config"]["grid"]} cubed and
|
| 144 |
+
it has {meta["parameters"]:,} parameters. Selected checkpoint: step {checkpoint["step"]};
|
| 145 |
+
completed run: {meta["steps_requested"]} steps.
|
| 146 |
+
|
| 147 |
+
## Actual training data and preprocessing
|
| 148 |
+
|
| 149 |
+
Only the datasets listed above were used, with per-asset provenance in ATTRIBUTIONS.json.
|
| 150 |
+
Scenario assets are CC-BY-4.0; the Objaverse subset is CC0. Original objects were centered
|
| 151 |
+
and uniformly scaled into a 0.9-wide cube, surface sampled, and converted to isotropic
|
| 152 |
+
Gaussian proxy targets. Orthographic images were rendered from these same proxy clouds.
|
| 153 |
+
This is not teacher distillation from Idol, Hunyuan, InstantMesh, or Hi3D, and it did not
|
| 154 |
+
train on natural photographs, MultiScan, 3D-Front, Show3D, or Voxel51 scene splats.
|
| 155 |
+
|
| 156 |
+
Related source inputs and all views stay in the same object group. A separate 15% test
|
| 157 |
+
partition is excluded from training and validation-based checkpoint selection.
|
| 158 |
+
|
| 159 |
+
## Measured results
|
| 160 |
+
|
| 161 |
+
Independent test objects: {report["test_objects"]}; test views: {report["test_samples"]}.
|
| 162 |
+
Base test loss: {report["baseline_test"]["loss"]:.6f}; post-trained test loss:
|
| 163 |
+
{report["posttrained_test"]["loss"]:.6f}. Base occupancy IoU:
|
| 164 |
+
{report["baseline_test"]["occupancy_iou"]:.6f}; post-trained occupancy IoU:
|
| 165 |
+
{report["posttrained_test"]["occupancy_iou"]:.6f}.
|
| 166 |
+
See evaluation.json for the full results and checks. These scores measure coarse proxy
|
| 167 |
+
reconstruction on the rendered data distribution; they do not prove photo realism,
|
| 168 |
+
watertight meshes, production quality, or texture fidelity. Near duplicates can remain
|
| 169 |
+
despite source grouping and exact-byte deduplication.
|
| 170 |
+
|
| 171 |
+
## Run on a Mac
|
| 172 |
+
|
| 173 |
+
Download this repository, then run `bash setup-mac.sh` and
|
| 174 |
+
`source "$HOME/Library/Application Support/Forma3D/venv/bin/activate"`.
|
| 175 |
+
|
| 176 |
+
```sh
|
| 177 |
+
image3d generate --checkpoint model.pt --image your-centered-cutout.png \\
|
| 178 |
+
--out results/object.ply --device mps
|
| 179 |
+
image3d preview --ply results/object.ply --out results/preview.png
|
| 180 |
+
```
|
| 181 |
+
|
| 182 |
+
Inputs are centered objects on black, matching the training framing. Natural photos
|
| 183 |
+
are outside the verified distribution. Output is Gaussian PLY, not a triangle mesh.
|
| 184 |
+
CPU works with `--device cpu`; CUDA support is implemented but was not tested on the
|
| 185 |
+
Mac used to prepare these scripts.
|
| 186 |
+
|
| 187 |
+
## License and attribution
|
| 188 |
+
|
| 189 |
+
Source code and these weights are offered under Apache-2.0. Dataset and individual
|
| 190 |
+
asset licenses remain separate; retain ATTRIBUTIONS.json and consult DATASETS.md.
|
| 191 |
+
This license statement does not grant rights to third-party trademarks or likenesses.
|
| 192 |
+
See COMMANDS.md for reproduction commands.
|
| 193 |
+
'''
|
| 194 |
+
(release / "README.md").write_text(text)
|
| 195 |
+
sums = [sha(p) + " " + str(p.relative_to(release)) for p in sorted(release.rglob("*")) if p.is_file()]
|
| 196 |
+
(release / "SHA256SUMS").write_text("\n".join(sums) + "\n")
|
| 197 |
+
return release
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
def main():
|
| 201 |
+
p = argparse.ArgumentParser(description=__doc__)
|
| 202 |
+
p.add_argument("--run", required=True)
|
| 203 |
+
p.add_argument("--data", required=True)
|
| 204 |
+
p.add_argument("--base", required=True)
|
| 205 |
+
p.add_argument("--release", default="release/forma3d-tiny")
|
| 206 |
+
p.add_argument("--repo", default="Lucasgitguy-co/forma3d-tiny")
|
| 207 |
+
p.add_argument("--device", choices=["mps", "cpu", "cuda", "auto"], default="mps")
|
| 208 |
+
p.add_argument("--publish", action="store_true")
|
| 209 |
+
args = p.parse_args()
|
| 210 |
+
checkpoint, meta, report = evaluate_release(args)
|
| 211 |
+
release = stage(args, checkpoint, meta, report)
|
| 212 |
+
if args.publish:
|
| 213 |
+
from huggingface_hub import HfApi
|
| 214 |
+
api = HfApi()
|
| 215 |
+
# Refuse accidental replacement of a previously published model.
|
| 216 |
+
if api.repo_exists(args.repo, repo_type="model"):
|
| 217 |
+
raise ValueError("Repository already exists. Choose a new --repo; no overwrite was performed.")
|
| 218 |
+
api.create_repo(args.repo, repo_type="model", private=True)
|
| 219 |
+
commit = api.upload_folder(repo_id=args.repo, folder_path=release,
|
| 220 |
+
commit_message="Publish evaluated Forma3D-Tiny v0.2")
|
| 221 |
+
api.update_repo_settings(args.repo, private=False)
|
| 222 |
+
print(f"Published https://huggingface.co/{args.repo} at {commit.oid}")
|
| 223 |
+
else:
|
| 224 |
+
print(f"Evaluated release staged at {release}; nothing published.")
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
if __name__ == "__main__":
|
| 228 |
+
main()
|
setup-mac.sh
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
set -euo pipefail
|
| 3 |
+
cd "$(dirname "$0")"
|
| 4 |
+
if ! command -v uv >/dev/null 2>&1; then
|
| 5 |
+
echo 'Install uv first: brew install uv' >&2
|
| 6 |
+
exit 1
|
| 7 |
+
fi
|
| 8 |
+
# Keep native libraries out of Documents, where macOS can offload their contents.
|
| 9 |
+
FORMA3D_RUNTIME_DIR="${FORMA3D_RUNTIME_DIR:-$HOME/Library/Application Support/Forma3D}"
|
| 10 |
+
export UV_CACHE_DIR="$FORMA3D_RUNTIME_DIR/uv-cache"
|
| 11 |
+
mkdir -p "$FORMA3D_RUNTIME_DIR"
|
| 12 |
+
uv venv --python 3.11 --allow-existing "$FORMA3D_RUNTIME_DIR/venv"
|
| 13 |
+
uv pip install --python "$FORMA3D_RUNTIME_DIR/venv/bin/python" \
|
| 14 |
+
-r requirements-tested-macos.txt "$PWD[data,test]"
|
| 15 |
+
"$FORMA3D_RUNTIME_DIR/venv/bin/python" -m image3d_student.cli doctor
|
src/image3d_student/__init__.py
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
# Copyright 2026 Lucasgitguy-co
|
| 3 |
+
"""Research prototype; no pretrained general-purpose student weights are bundled."""
|
| 4 |
+
|
| 5 |
+
__version__ = "0.2.0"
|
src/image3d_student/cli.py
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
# Copyright 2026 Lucasgitguy-co
|
| 3 |
+
import argparse
|
| 4 |
+
import importlib.util
|
| 5 |
+
import json
|
| 6 |
+
import platform
|
| 7 |
+
import shutil
|
| 8 |
+
import sys
|
| 9 |
+
from pathlib import Path
|
| 10 |
+
|
| 11 |
+
import torch
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def parser():
|
| 15 |
+
p = argparse.ArgumentParser(description="Local image-to-Gaussian student research prototype")
|
| 16 |
+
sub = p.add_subparsers(dest="command", required=True)
|
| 17 |
+
sub.add_parser("doctor", help="Check dependencies, Metal availability and disk space; no downloads")
|
| 18 |
+
demo = sub.add_parser("demo-data", help="Create synthetic code-test fixtures, NOT teacher data")
|
| 19 |
+
demo.add_argument("--out", required=True)
|
| 20 |
+
demo.add_argument("--count", type=int, default=12)
|
| 21 |
+
demo.add_argument("--grid", type=int, choices=[8,16,32], default=8)
|
| 22 |
+
cache = sub.add_parser("cache", help="Cache Idol PLY with optional aligned geometry teacher meshes")
|
| 23 |
+
cache.add_argument("--image", required=True, help="Exact prepared/framed input used by teacher")
|
| 24 |
+
cache.add_argument("--idol-ply", required=True)
|
| 25 |
+
cache.add_argument("--out", required=True)
|
| 26 |
+
cache.add_argument("--id", required=True)
|
| 27 |
+
cache.add_argument("--object-id", help="Shared ID for all images of the same object, to prevent validation leakage")
|
| 28 |
+
cache.add_argument("--grid", type=int, choices=[8,16,32], default=16)
|
| 29 |
+
cache.add_argument("--coarse-mesh", help="InstantMesh output; this command imports, does not run InstantMesh")
|
| 30 |
+
cache.add_argument("--coarse-transform", help="JSON 4x4 mesh-to-Idol-PLY matrix")
|
| 31 |
+
cache.add_argument("--fine-mesh", help="Hi3D output; this command imports, does not run Hi3D")
|
| 32 |
+
cache.add_argument("--fine-transform", help="JSON 4x4 mesh-to-Idol-PLY matrix")
|
| 33 |
+
train = sub.add_parser("train", help="Train the student on cached targets")
|
| 34 |
+
train.add_argument("--manifest", required=True)
|
| 35 |
+
train.add_argument("--out", required=True)
|
| 36 |
+
train.add_argument("--device", choices=["auto","cuda","mps","cpu"], default="auto")
|
| 37 |
+
train.add_argument("--init-from", help="Post-train checkpoint weights; optimizer starts fresh")
|
| 38 |
+
train.add_argument("--steps", type=int, default=1000)
|
| 39 |
+
train.add_argument("--batch-size", type=int, default=1)
|
| 40 |
+
train.add_argument("--width", type=int, default=128)
|
| 41 |
+
train.add_argument("--lr", type=float, default=3e-4)
|
| 42 |
+
train.add_argument("--seed", type=int, default=42)
|
| 43 |
+
train.add_argument("--eval-every", type=int, default=50)
|
| 44 |
+
train.add_argument("--validation-fraction", type=float, default=.2)
|
| 45 |
+
train.add_argument("--allow-synthetic", action="store_true")
|
| 46 |
+
generate = sub.add_parser("generate", help="Generate standard 3DGS PLY with a trained student")
|
| 47 |
+
generate.add_argument("--checkpoint", required=True)
|
| 48 |
+
generate.add_argument("--image", required=True, help="Centered cutout or teacher-prepared image, black background")
|
| 49 |
+
generate.add_argument("--out", required=True)
|
| 50 |
+
generate.add_argument("--device", choices=["auto","cuda","mps","cpu"], default="auto")
|
| 51 |
+
generate.add_argument("--threshold", type=float, default=.5)
|
| 52 |
+
generate.add_argument("--max-splats", type=int, default=32768)
|
| 53 |
+
render = sub.add_parser("preview", help="CPU diagnostic turntable contact sheet")
|
| 54 |
+
render.add_argument("--ply", required=True)
|
| 55 |
+
render.add_argument("--out", required=True)
|
| 56 |
+
teacher = sub.add_parser("teacher-idol", help="EXPERIMENTAL staged Mac runner; weights not bundled")
|
| 57 |
+
teacher.add_argument("--image", required=True)
|
| 58 |
+
teacher.add_argument("--out", required=True)
|
| 59 |
+
teacher.add_argument("--cache", default=".cache/huggingface")
|
| 60 |
+
teacher.add_argument("--weights", default="speridlabs/idol")
|
| 61 |
+
teacher.add_argument("--device", choices=["mps","cpu"], default="mps")
|
| 62 |
+
teacher.add_argument("--mode", choices=["real","synthetic"], default="synthetic")
|
| 63 |
+
teacher.add_argument("--steps", type=int, default=20)
|
| 64 |
+
teacher.add_argument("--gaussians", type=int, default=32768)
|
| 65 |
+
teacher.add_argument("--query-chunk", type=int, default=128)
|
| 66 |
+
teacher.add_argument("--seed", type=int, default=42)
|
| 67 |
+
teacher.add_argument("--allow-download", action="store_true", help="Explicitly allow downloading model weights and gated encoders")
|
| 68 |
+
return p
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
def main():
|
| 72 |
+
p = parser()
|
| 73 |
+
args = p.parse_args()
|
| 74 |
+
try:
|
| 75 |
+
if args.command == "doctor":
|
| 76 |
+
report = {"python": platform.python_version(), "platform": platform.platform(), "torch": str(torch.__version__),
|
| 77 |
+
"mps_available": torch.backends.mps.is_available(), "mps_built": torch.backends.mps.is_built(),
|
| 78 |
+
"free_disk_gib": round(shutil.disk_usage(Path.cwd()).free / 1024**3, 2),
|
| 79 |
+
"idol_installed": importlib.util.find_spec("idol") is not None,
|
| 80 |
+
"teacher_status": {"Idol": "experimental adapter, real weights unverified",
|
| 81 |
+
"InstantMesh": "cached mesh import only; no Mac execution adapter",
|
| 82 |
+
"Hi3D": "cached mesh import only; no Mac execution adapter"},
|
| 83 |
+
"weights_bundled": False, "quantization": "FP32 student; no binary kernels or 1-bit claims"}
|
| 84 |
+
print(json.dumps(report, indent=2))
|
| 85 |
+
elif args.command == "demo-data":
|
| 86 |
+
from .demo import create_demo
|
| 87 |
+
print(create_demo(args.out, args.count, args.grid))
|
| 88 |
+
elif args.command == "cache":
|
| 89 |
+
from .data import cache_sample
|
| 90 |
+
from .splats import read_ply
|
| 91 |
+
print(json.dumps(cache_sample(args.out, args.id, args.image, read_ply(args.idol_ply), args.grid,
|
| 92 |
+
coarse=args.coarse_mesh, coarse_transform=args.coarse_transform,
|
| 93 |
+
fine=args.fine_mesh, fine_transform=args.fine_transform,
|
| 94 |
+
extra={"object_id": args.object_id or args.id, "idol_ply": str(Path(args.idol_ply).resolve())}), indent=2))
|
| 95 |
+
elif args.command == "train":
|
| 96 |
+
from .engine import train
|
| 97 |
+
train(args)
|
| 98 |
+
elif args.command == "generate":
|
| 99 |
+
from .engine import generate
|
| 100 |
+
print(json.dumps(generate(args.checkpoint, args.image, args.out, args.device, args.threshold, args.max_splats), indent=2))
|
| 101 |
+
elif args.command == "preview":
|
| 102 |
+
from PIL import Image, ImageDraw
|
| 103 |
+
import numpy as np
|
| 104 |
+
from .splats import preview, read_ply
|
| 105 |
+
splats = read_ply(args.ply)
|
| 106 |
+
sheet = Image.new("RGB", (1024, 280), "#111111")
|
| 107 |
+
draw = ImageDraw.Draw(sheet)
|
| 108 |
+
for i in range(4):
|
| 109 |
+
sheet.paste(preview(splats, yaw=i*np.pi/2), (i*256, 24))
|
| 110 |
+
draw.text((i*256+8, 6), f"{i*90} degrees - diagnostic view", fill="white")
|
| 111 |
+
out = Path(args.out)
|
| 112 |
+
if out.exists():
|
| 113 |
+
raise ValueError("Preview already exists")
|
| 114 |
+
out.parent.mkdir(parents=True, exist_ok=True)
|
| 115 |
+
sheet.save(out)
|
| 116 |
+
elif args.command == "teacher-idol":
|
| 117 |
+
from .teacher_idol import run_idol
|
| 118 |
+
run_idol(args)
|
| 119 |
+
except (ValueError, RuntimeError, FileNotFoundError, ImportError) as exc:
|
| 120 |
+
print(f"Error: {exc}", file=sys.stderr)
|
| 121 |
+
return 2
|
| 122 |
+
return 0
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
if __name__ == "__main__":
|
| 126 |
+
raise SystemExit(main())
|
src/image3d_student/data.py
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
# Copyright 2026 Lucasgitguy-co
|
| 3 |
+
import hashlib
|
| 4 |
+
import json
|
| 5 |
+
from pathlib import Path
|
| 6 |
+
|
| 7 |
+
import numpy as np
|
| 8 |
+
import torch
|
| 9 |
+
from PIL import Image, ImageOps
|
| 10 |
+
from torch.utils.data import Dataset
|
| 11 |
+
|
| 12 |
+
from .splats import Splats, read_ply
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def grid_centers(grid):
|
| 16 |
+
axis = (np.arange(grid, dtype=np.float32) + .5) / grid - .5
|
| 17 |
+
return np.stack(np.meshgrid(axis, axis, axis, indexing="ij"), axis=-1).reshape(-1, 3)
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def cell_indices(xyz, grid):
|
| 21 |
+
if not np.isfinite(xyz).all() or (np.abs(xyz) > .50001).any():
|
| 22 |
+
raise ValueError("Targets must be aligned inside [-0.5,0.5]^3. No silent normalization is performed.")
|
| 23 |
+
ijk = np.floor((xyz + .5) * grid).astype(np.int64).clip(0, grid-1)
|
| 24 |
+
return (ijk[:, 0] * grid + ijk[:, 1]) * grid + ijk[:, 2]
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def splat_targets(splats, grid):
|
| 28 |
+
"""One highest-opacity teacher Gaussian per occupied cell; explicitly lossy."""
|
| 29 |
+
cells = cell_indices(splats.xyz, grid)
|
| 30 |
+
order = np.argsort(-splats.opacity[:, 0], kind="stable")
|
| 31 |
+
_, first = np.unique(cells[order], return_index=True)
|
| 32 |
+
keep = order[first]
|
| 33 |
+
slots = cells[keep]
|
| 34 |
+
result = {"occ": np.zeros((grid**3, 1), np.float32), "xyz": grid_centers(grid),
|
| 35 |
+
"rgb": np.zeros((grid**3, 3), np.float32),
|
| 36 |
+
"scale": np.full((grid**3, 3), 1 / grid / 3, np.float32),
|
| 37 |
+
"quat": np.tile(np.array([1, 0, 0, 0], np.float32), (grid**3, 1)),
|
| 38 |
+
"opacity": np.zeros((grid**3, 1), np.float32),
|
| 39 |
+
"geometry": np.zeros((grid**3, 2), np.float32),
|
| 40 |
+
"geometry_valid": np.zeros(2, np.float32), "grid": np.array(grid, np.int32)}
|
| 41 |
+
result["occ"][slots] = 1
|
| 42 |
+
for key in ("xyz", "rgb", "scale", "quat", "opacity"):
|
| 43 |
+
result[key][slots] = getattr(splats, key)[keep]
|
| 44 |
+
return result
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def mesh_occupancy(path, transform_path, grid):
|
| 48 |
+
import trimesh
|
| 49 |
+
if not transform_path:
|
| 50 |
+
raise ValueError("Every geometry teacher needs an explicit --*-transform JSON matrix, even for identity.")
|
| 51 |
+
transform = np.asarray(json.loads(Path(transform_path).read_text()), dtype=float)
|
| 52 |
+
if transform.shape != (4, 4) or not np.isfinite(transform).all() or not np.allclose(transform[3], [0,0,0,1]):
|
| 53 |
+
raise ValueError("Transform must be a finite affine 4x4 matrix")
|
| 54 |
+
mesh = trimesh.load(str(path), force="mesh", process=False)
|
| 55 |
+
if not isinstance(mesh, trimesh.Trimesh) or len(mesh.faces) == 0:
|
| 56 |
+
raise ValueError("Geometry teacher must contain a triangle mesh")
|
| 57 |
+
mesh.apply_transform(transform)
|
| 58 |
+
cell_indices(np.asarray(mesh.vertices), grid) # validates the whole object
|
| 59 |
+
points, _ = trimesh.sample.sample_surface(mesh, min(200_000, grid**3 * 16), seed=42)
|
| 60 |
+
mask = np.zeros(grid**3, np.float32)
|
| 61 |
+
mask[np.unique(cell_indices(points, grid))] = 1
|
| 62 |
+
return mask
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
def cache_sample(root, sample_id, image_path, splats, grid=16, source="idol",
|
| 66 |
+
coarse=None, coarse_transform=None, fine=None, fine_transform=None, extra=None):
|
| 67 |
+
root = Path(root)
|
| 68 |
+
if not sample_id or any(c not in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_" for c in sample_id):
|
| 69 |
+
raise ValueError("Sample ID may contain only letters, digits, - and _")
|
| 70 |
+
if grid not in (8, 16, 32):
|
| 71 |
+
raise ValueError("Grid must be 8, 16 or 32")
|
| 72 |
+
target = splat_targets(splats, grid)
|
| 73 |
+
for channel, mesh, transform in [(0, coarse, coarse_transform), (1, fine, fine_transform)]:
|
| 74 |
+
if mesh:
|
| 75 |
+
target["geometry"][:, channel] = mesh_occupancy(mesh, transform, grid)
|
| 76 |
+
target["geometry_valid"][channel] = 1
|
| 77 |
+
row = {"id": sample_id, "image": f"images/{sample_id}.png", "target": f"targets/{sample_id}.npz",
|
| 78 |
+
"source": source, "grid": grid, "teachers": {"appearance": source,
|
| 79 |
+
"coarse": "InstantMesh" if coarse else None, "fine": "Hi3D" if fine else None},
|
| 80 |
+
"teacher_gaussians": len(splats.xyz), "retained_gaussians": int(target["occ"].sum()),
|
| 81 |
+
"geometry_transforms": {"coarse": json.loads(Path(coarse_transform).read_text()) if coarse else None,
|
| 82 |
+
"fine": json.loads(Path(fine_transform).read_text()) if fine else None},
|
| 83 |
+
"metadata": extra or {}}
|
| 84 |
+
manifest = root / "manifest.jsonl"
|
| 85 |
+
rows = load_manifest(manifest) if manifest.exists() else []
|
| 86 |
+
if any(r["id"] == sample_id for r in rows):
|
| 87 |
+
raise ValueError(f"Sample {sample_id} already exists; choose a new ID")
|
| 88 |
+
if rows and any(r["grid"] != grid for r in rows):
|
| 89 |
+
raise ValueError("Do not mix grid resolutions in one dataset")
|
| 90 |
+
image = Image.open(image_path)
|
| 91 |
+
image.load()
|
| 92 |
+
if root.joinpath(row["image"]).exists() or root.joinpath(row["target"]).exists():
|
| 93 |
+
raise ValueError("Sample files already exist; refusing to overwrite")
|
| 94 |
+
root.joinpath("images").mkdir(parents=True, exist_ok=True)
|
| 95 |
+
root.joinpath("targets").mkdir(parents=True, exist_ok=True)
|
| 96 |
+
image.save(root / row["image"])
|
| 97 |
+
row["image_sha256"] = hashlib.sha256((root / row["image"]).read_bytes()).hexdigest()
|
| 98 |
+
np.savez_compressed(root / row["target"], **target)
|
| 99 |
+
row["target_sha256"] = hashlib.sha256((root / row["target"]).read_bytes()).hexdigest()
|
| 100 |
+
# Single-writer dataset. Atomic manifest replacement avoids partial JSON lines.
|
| 101 |
+
tmp = manifest.with_suffix(".tmp")
|
| 102 |
+
tmp.write_text("".join(json.dumps(r) + "\n" for r in [*rows, row]))
|
| 103 |
+
tmp.replace(manifest)
|
| 104 |
+
return row
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
def load_manifest(path):
|
| 108 |
+
rows = [json.loads(line) for line in Path(path).read_text().splitlines() if line.strip()]
|
| 109 |
+
if not rows or len({r["id"] for r in rows}) != len(rows):
|
| 110 |
+
raise ValueError("Manifest must contain nonempty, unique sample IDs")
|
| 111 |
+
return rows
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
def image_tensor(path, size=128):
|
| 115 |
+
"""Already-framed RGB or RGBA cutout; black background, square letterbox."""
|
| 116 |
+
with Image.open(path) as original:
|
| 117 |
+
rgba = ImageOps.exif_transpose(original).convert("RGBA")
|
| 118 |
+
bg = Image.new("RGBA", rgba.size, (0, 0, 0, 255))
|
| 119 |
+
bg.alpha_composite(rgba)
|
| 120 |
+
image = ImageOps.pad(bg.convert("RGB"), (size, size), method=Image.Resampling.LANCZOS, color="black")
|
| 121 |
+
return torch.from_numpy(np.array(image, dtype=np.float32).transpose(2, 0, 1) / 255)
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
class CachedDataset(Dataset):
|
| 125 |
+
def __init__(self, manifest, rows=None):
|
| 126 |
+
self.root = Path(manifest).resolve().parent
|
| 127 |
+
self.rows = load_manifest(manifest) if rows is None else rows
|
| 128 |
+
if not self.rows:
|
| 129 |
+
raise ValueError("Empty dataset")
|
| 130 |
+
self.grid = self.rows[0]["grid"]
|
| 131 |
+
for row in self.rows:
|
| 132 |
+
if row["grid"] != self.grid:
|
| 133 |
+
raise ValueError("Mixed grids")
|
| 134 |
+
for key in ("image", "target"):
|
| 135 |
+
p = (self.root / row[key]).resolve()
|
| 136 |
+
if not p.is_relative_to(self.root) or not p.is_file():
|
| 137 |
+
raise ValueError(f"Invalid dataset {key} path")
|
| 138 |
+
digest = hashlib.sha256(p.read_bytes()).hexdigest()
|
| 139 |
+
if digest != row[f"{key}_sha256"]:
|
| 140 |
+
raise ValueError(f"Dataset {key} hash mismatch for {row['id']}")
|
| 141 |
+
|
| 142 |
+
def __len__(self):
|
| 143 |
+
return len(self.rows)
|
| 144 |
+
|
| 145 |
+
def __getitem__(self, i):
|
| 146 |
+
row = self.rows[i]
|
| 147 |
+
with np.load(self.root / row["target"], allow_pickle=False) as cached:
|
| 148 |
+
target = {k: torch.from_numpy(cached[k].copy()).float() for k in cached.files if k != "grid"}
|
| 149 |
+
return image_tensor(self.root / row["image"]), target
|
src/image3d_student/demo.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
# Copyright 2026 Lucasgitguy-co
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
|
| 5 |
+
import numpy as np
|
| 6 |
+
|
| 7 |
+
from .data import cache_sample
|
| 8 |
+
from .splats import Splats, preview
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def create_demo(root, count=12, grid=8):
|
| 12 |
+
"""Procedural ellipsoids only. Never presented as outputs of any real teacher."""
|
| 13 |
+
if count < 4:
|
| 14 |
+
raise ValueError("Use at least four fixtures")
|
| 15 |
+
root = Path(root)
|
| 16 |
+
root.mkdir(parents=True, exist_ok=True)
|
| 17 |
+
rng = np.random.default_rng(17)
|
| 18 |
+
phi, theta = np.meshgrid(np.linspace(.06, np.pi-.06, 14), np.linspace(0, 2*np.pi, 28, endpoint=False))
|
| 19 |
+
unit = np.stack([np.sin(phi)*np.cos(theta), np.cos(phi), np.sin(phi)*np.sin(theta)], axis=-1).reshape(-1, 3)
|
| 20 |
+
for i in range(count):
|
| 21 |
+
radii = rng.uniform(.17, .36, 3)
|
| 22 |
+
xyz = (unit * radii).astype(np.float32)
|
| 23 |
+
colour = rng.uniform(.2, .95, 3)
|
| 24 |
+
rgb = np.clip(colour[None] * (.8 + .2 * unit[:, 1:2]), 0, 1)
|
| 25 |
+
splats = Splats(xyz, rgb, np.full_like(xyz, .035), np.tile([1,0,0,0], (len(xyz),1)), np.full((len(xyz),1), .9))
|
| 26 |
+
image_path = root / f"fixture-{i:03}.png"
|
| 27 |
+
preview(splats, size=128).save(image_path)
|
| 28 |
+
cache_sample(root, f"fixture-{i:03}", image_path, splats, grid, source="synthetic",
|
| 29 |
+
extra={"purpose": "code verification only", "object_id": f"fixture-{i:03}"})
|
| 30 |
+
image_path.unlink()
|
| 31 |
+
return root / "manifest.jsonl"
|
src/image3d_student/engine.py
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
# Copyright 2026 Lucasgitguy-co
|
| 3 |
+
import json
|
| 4 |
+
import hashlib
|
| 5 |
+
import random
|
| 6 |
+
import time
|
| 7 |
+
from pathlib import Path
|
| 8 |
+
|
| 9 |
+
import numpy as np
|
| 10 |
+
import torch
|
| 11 |
+
from torch.utils.data import DataLoader
|
| 12 |
+
|
| 13 |
+
from .data import CachedDataset, image_tensor, load_manifest
|
| 14 |
+
from .model import Student, distillation_loss
|
| 15 |
+
from .splats import Splats, write_ply
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def device_for(name="auto"):
|
| 19 |
+
if name == "auto":
|
| 20 |
+
name = "cuda" if torch.cuda.is_available() else ("mps" if torch.backends.mps.is_available() else "cpu")
|
| 21 |
+
if name == "mps" and not torch.backends.mps.is_available():
|
| 22 |
+
raise ValueError("Metal GPU unavailable in this process. Run in a normal macOS Terminal, or use --device cpu.")
|
| 23 |
+
if name == "cuda" and not torch.cuda.is_available():
|
| 24 |
+
raise ValueError("CUDA requested but unavailable")
|
| 25 |
+
if name not in ("mps", "cpu", "cuda"):
|
| 26 |
+
raise ValueError("Supported devices: cpu, mps, cuda")
|
| 27 |
+
torch.set_num_threads(min(4, torch.get_num_threads()))
|
| 28 |
+
return torch.device(name)
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def split_rows(rows, fraction, seed):
|
| 32 |
+
if not 0 <= fraction < 1:
|
| 33 |
+
raise ValueError("Validation fraction must lie in [0,1)")
|
| 34 |
+
# Keep repeated views/crops of the same object together. Supply object_id in cache metadata.
|
| 35 |
+
groups = {}
|
| 36 |
+
for row in rows:
|
| 37 |
+
group = row.get("metadata", {}).get("object_id", row["id"])
|
| 38 |
+
groups.setdefault(group, []).append(row)
|
| 39 |
+
keys = sorted(groups)
|
| 40 |
+
random.Random(seed).shuffle(keys)
|
| 41 |
+
n = max(1, round(len(keys) * fraction)) if fraction else 0
|
| 42 |
+
if n >= len(keys):
|
| 43 |
+
raise ValueError("Need at least two different objects for validation, or explicitly use --validation-fraction 0 for an overfit test")
|
| 44 |
+
val_keys = set(keys[:n])
|
| 45 |
+
train = [r for k in keys if k not in val_keys for r in groups[k]]
|
| 46 |
+
val = [r for k in keys if k in val_keys for r in groups[k]]
|
| 47 |
+
if {r["image_sha256"] for r in train} & {r["image_sha256"] for r in val}:
|
| 48 |
+
raise ValueError("Identical images occur across training/validation. Assign the same object-id to related samples.")
|
| 49 |
+
return train, val
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def on_device(target, device):
|
| 53 |
+
return {k: v.to(device) for k, v in target.items()}
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
@torch.no_grad()
|
| 57 |
+
def evaluate(model, loader, device):
|
| 58 |
+
model.eval()
|
| 59 |
+
sums = {}
|
| 60 |
+
for image, target in loader:
|
| 61 |
+
target = on_device(target, device)
|
| 62 |
+
pred = model(image.to(device))
|
| 63 |
+
loss, terms = distillation_loss(pred, target, model.grid)
|
| 64 |
+
occupied = pred["occ"].sigmoid() > .5
|
| 65 |
+
truth = target["occ"] > .5
|
| 66 |
+
terms = {**terms, "loss": loss, "occupancy_iou": (occupied & truth).sum() / (occupied | truth).sum().clamp_min(1)}
|
| 67 |
+
for key, value in terms.items():
|
| 68 |
+
sums[key] = sums.get(key, 0.) + float(value)
|
| 69 |
+
return {k: v / len(loader) for k, v in sums.items()}
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
def save_checkpoint(path, model, optimizer, step, metadata):
|
| 73 |
+
payload = {"format": 1, "config": model.config, "model": {k: v.detach().cpu() for k, v in model.state_dict().items()},
|
| 74 |
+
"optimizer": optimizer.state_dict(), "step": step, "metadata": metadata}
|
| 75 |
+
tmp = Path(path).with_suffix(".tmp")
|
| 76 |
+
torch.save(payload, tmp)
|
| 77 |
+
tmp.replace(path)
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def train(args):
|
| 81 |
+
if args.steps < 1 or args.batch_size < 1 or args.lr <= 0 or args.eval_every < 1:
|
| 82 |
+
raise ValueError("Steps, batch size, learning rate, and evaluation interval must be positive")
|
| 83 |
+
device = device_for(args.device)
|
| 84 |
+
random.seed(args.seed)
|
| 85 |
+
np.random.seed(args.seed)
|
| 86 |
+
torch.manual_seed(args.seed)
|
| 87 |
+
rows = load_manifest(args.manifest)
|
| 88 |
+
synthetic = any(r["source"] == "synthetic" for r in rows)
|
| 89 |
+
if synthetic and not args.allow_synthetic:
|
| 90 |
+
raise ValueError("Synthetic fixtures are code tests, not teacher data. Add --allow-synthetic for an explicit smoke test.")
|
| 91 |
+
train_rows, val_rows = split_rows(rows, args.validation_fraction, args.seed)
|
| 92 |
+
train_data = CachedDataset(args.manifest, train_rows)
|
| 93 |
+
generator = torch.Generator().manual_seed(args.seed)
|
| 94 |
+
loader = DataLoader(train_data, batch_size=args.batch_size, shuffle=True, num_workers=0, generator=generator)
|
| 95 |
+
val_loader = DataLoader(CachedDataset(args.manifest, val_rows), batch_size=1) if val_rows else None
|
| 96 |
+
model = Student(train_data.grid, args.width).to(device)
|
| 97 |
+
initialization = None
|
| 98 |
+
if getattr(args, "init_from", None):
|
| 99 |
+
initial_path = Path(args.init_from)
|
| 100 |
+
state = torch.load(initial_path, map_location="cpu", weights_only=True)
|
| 101 |
+
if state.get("format") != 1 or state["config"]["width"] != args.width:
|
| 102 |
+
raise ValueError("Initialization requires format=1 and matching --width")
|
| 103 |
+
# Coordinates are deterministic buffers, not learned weights. Rebuild them
|
| 104 |
+
# for the target grid while preserving every learned encoder/decoder weight.
|
| 105 |
+
learned = {k: v for k, v in state["model"].items() if k not in ("centers", "coords")}
|
| 106 |
+
result = model.load_state_dict(learned, strict=False)
|
| 107 |
+
if set(result.missing_keys) != {"centers", "coords"} or result.unexpected_keys:
|
| 108 |
+
raise ValueError("Checkpoint architecture mismatch")
|
| 109 |
+
initialization = {"sha256": hashlib.sha256(initial_path.read_bytes()).hexdigest(),
|
| 110 |
+
"config": state["config"], "step": state["step"],
|
| 111 |
+
"optimizer": "fresh AdamW; weights-only post-training"}
|
| 112 |
+
optimizer = torch.optim.AdamW(model.parameters(), lr=args.lr, weight_decay=1e-4)
|
| 113 |
+
run = Path(args.out)
|
| 114 |
+
if run.exists() and any(run.iterdir()):
|
| 115 |
+
raise ValueError("Run directory must be empty; choose a new --out directory")
|
| 116 |
+
run.mkdir(parents=True, exist_ok=True)
|
| 117 |
+
meta = {"synthetic_only": all(r["source"] == "synthetic" for r in rows),
|
| 118 |
+
"contains_synthetic": synthetic, "device": str(device), "torch": str(torch.__version__),
|
| 119 |
+
"seed": args.seed, "train_ids": [r["id"] for r in train_rows], "val_ids": [r["id"] for r in val_rows],
|
| 120 |
+
"parameters": sum(p.numel() for p in model.parameters()),
|
| 121 |
+
"teachers": sorted({v for r in rows for v in r["teachers"].values() if v}),
|
| 122 |
+
"validation": "held-out objects" if val_rows else "none; training overfit test only",
|
| 123 |
+
"dataset": str(Path(args.manifest).resolve()),
|
| 124 |
+
"manifest_sha256": hashlib.sha256(Path(args.manifest).read_bytes()).hexdigest(),
|
| 125 |
+
"initialization": initialization, "steps_requested": args.steps,
|
| 126 |
+
"learning_rate": args.lr, "batch_size": args.batch_size,
|
| 127 |
+
"validation_fraction": args.validation_fraction}
|
| 128 |
+
if val_loader:
|
| 129 |
+
meta["baseline_validation"] = evaluate(model, val_loader, device)
|
| 130 |
+
(run / "run.json").write_text(json.dumps(meta, indent=2))
|
| 131 |
+
print(json.dumps(meta), flush=True)
|
| 132 |
+
step, best, started = 0, float("inf"), time.monotonic()
|
| 133 |
+
iterator = iter(loader)
|
| 134 |
+
try:
|
| 135 |
+
while step < args.steps:
|
| 136 |
+
try:
|
| 137 |
+
images, target = next(iterator)
|
| 138 |
+
except StopIteration:
|
| 139 |
+
iterator = iter(loader)
|
| 140 |
+
images, target = next(iterator)
|
| 141 |
+
model.train()
|
| 142 |
+
optimizer.zero_grad(set_to_none=True)
|
| 143 |
+
pred = model(images.to(device))
|
| 144 |
+
loss, terms = distillation_loss(pred, on_device(target, device), model.grid)
|
| 145 |
+
if not torch.isfinite(loss):
|
| 146 |
+
raise RuntimeError("Nonfinite training loss; stopping")
|
| 147 |
+
loss.backward()
|
| 148 |
+
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.)
|
| 149 |
+
optimizer.step()
|
| 150 |
+
step += 1
|
| 151 |
+
if step == 1 or step % args.eval_every == 0 or step == args.steps:
|
| 152 |
+
record = {"step": step, "seconds": round(time.monotonic()-started, 3),
|
| 153 |
+
"train_loss": float(loss.detach()), **{k: float(v.detach()) for k, v in terms.items()}}
|
| 154 |
+
if val_loader:
|
| 155 |
+
record["validation"] = evaluate(model, val_loader, device)
|
| 156 |
+
score = record["validation"]["loss"]
|
| 157 |
+
if score < best:
|
| 158 |
+
best = score
|
| 159 |
+
save_checkpoint(run / "best.pt", model, optimizer, step, meta)
|
| 160 |
+
with (run / "metrics.jsonl").open("a") as handle:
|
| 161 |
+
handle.write(json.dumps(record) + "\n")
|
| 162 |
+
print(json.dumps(record), flush=True)
|
| 163 |
+
save_checkpoint(run / "last.pt", model, optimizer, step, meta)
|
| 164 |
+
except KeyboardInterrupt:
|
| 165 |
+
print("Interrupted; saving completed optimizer steps.", flush=True)
|
| 166 |
+
finally:
|
| 167 |
+
if step:
|
| 168 |
+
save_checkpoint(run / "last.pt", model, optimizer, step, meta)
|
| 169 |
+
return meta
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
@torch.no_grad()
|
| 173 |
+
def generate(checkpoint, image, out, device="auto", threshold=.5, max_splats=32768):
|
| 174 |
+
if not 0 < threshold < 1 or max_splats < 1:
|
| 175 |
+
raise ValueError("Threshold must be in (0,1) and max-splats positive")
|
| 176 |
+
device = device_for(device)
|
| 177 |
+
state = torch.load(checkpoint, map_location="cpu", weights_only=True)
|
| 178 |
+
if state.get("format") != 1 or state.get("step", 0) < 1:
|
| 179 |
+
raise ValueError("Expected a trained image3d-student checkpoint")
|
| 180 |
+
model = Student(**state["config"])
|
| 181 |
+
model.load_state_dict(state["model"])
|
| 182 |
+
model.to(device).eval()
|
| 183 |
+
if device.type == "mps":
|
| 184 |
+
torch.mps.synchronize()
|
| 185 |
+
started = time.monotonic()
|
| 186 |
+
pred = model(image_tensor(image)[None].to(device))
|
| 187 |
+
score = pred["occ"][0, :, 0].sigmoid()
|
| 188 |
+
valid = torch.nonzero(score >= threshold).flatten()
|
| 189 |
+
if len(valid) == 0:
|
| 190 |
+
raise ValueError("No occupied cells above threshold. Train longer or inspect validation; no fabricated fallback splats were exported.")
|
| 191 |
+
valid = valid[torch.argsort(score[valid], descending=True)[:max_splats]]
|
| 192 |
+
values = {k: pred[k][0, valid].cpu().numpy() for k in ("xyz", "rgb", "scale", "quat", "opacity")}
|
| 193 |
+
elapsed = time.monotonic() - started
|
| 194 |
+
splats = Splats(**values)
|
| 195 |
+
out = Path(out)
|
| 196 |
+
if out.exists() or out.with_suffix(".json").exists():
|
| 197 |
+
raise ValueError("Output already exists; choose a new filename")
|
| 198 |
+
write_ply(out, splats)
|
| 199 |
+
report = {"gaussians": len(valid), "seconds_preprocess_and_forward": elapsed,
|
| 200 |
+
"device": str(device), "checkpoint_step": state["step"], "training": state["metadata"],
|
| 201 |
+
"note": ("Synthetic-trained output is a pipeline demonstration, not a pretrained image-to-3D result."
|
| 202 |
+
if state["metadata"].get("contains_synthetic") else "Experimental cached-target student; inspect unseen-object quality.")}
|
| 203 |
+
out.with_suffix(".json").write_text(json.dumps(report, indent=2))
|
| 204 |
+
return report
|
src/image3d_student/model.py
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
# Copyright 2026 Lucasgitguy-co
|
| 3 |
+
import math
|
| 4 |
+
|
| 5 |
+
import torch
|
| 6 |
+
from torch import nn
|
| 7 |
+
from torch.nn import functional as F
|
| 8 |
+
|
| 9 |
+
from .data import grid_centers
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class Student(nn.Module):
|
| 13 |
+
"""Small image-conditioned coordinate MLP; fixed cells avoid unordered point regression.
|
| 14 |
+
|
| 15 |
+
15 Gaussian outputs + 2 auxiliary geometry logits. This is a coarse baseline,
|
| 16 |
+
not an architecture expected to reproduce million-splat teacher detail.
|
| 17 |
+
"""
|
| 18 |
+
def __init__(self, grid=16, width=128):
|
| 19 |
+
super().__init__()
|
| 20 |
+
if grid not in (8, 16, 32) or width < 16:
|
| 21 |
+
raise ValueError("Unsupported grid or width")
|
| 22 |
+
self.config = {"grid": grid, "width": width}
|
| 23 |
+
self.grid = grid
|
| 24 |
+
blocks, channels = [], 3
|
| 25 |
+
for out in (24, 48, 96, 128):
|
| 26 |
+
blocks.extend([nn.Conv2d(channels, out, 3, stride=2, padding=1), nn.GroupNorm(8, out), nn.SiLU()])
|
| 27 |
+
channels = out
|
| 28 |
+
self.encoder = nn.Sequential(*blocks, nn.AdaptiveAvgPool2d(4), nn.Flatten(),
|
| 29 |
+
nn.Linear(128*4*4, width), nn.SiLU())
|
| 30 |
+
centers = torch.from_numpy(grid_centers(grid))
|
| 31 |
+
freq = 2**torch.arange(4, dtype=torch.float32) * math.pi * 2
|
| 32 |
+
angles = centers[..., None] * freq
|
| 33 |
+
self.register_buffer("centers", centers)
|
| 34 |
+
self.register_buffer("coords", torch.cat([centers, angles.sin().flatten(1), angles.cos().flatten(1)], dim=1))
|
| 35 |
+
self.query = nn.Sequential(nn.Linear(27, width), nn.SiLU())
|
| 36 |
+
self.decoder = nn.Sequential(nn.Linear(width, width), nn.SiLU(), nn.Linear(width, width), nn.SiLU(), nn.Linear(width, 17))
|
| 37 |
+
with torch.no_grad():
|
| 38 |
+
self.decoder[-1].bias.zero_()
|
| 39 |
+
self.decoder[-1].bias[0] = -2
|
| 40 |
+
|
| 41 |
+
def forward(self, images):
|
| 42 |
+
features = self.encoder(images)
|
| 43 |
+
raw = self.decoder(features[:, None, :] + self.query(self.coords)[None])
|
| 44 |
+
quat = raw[..., 10:14] + raw.new_tensor([1, 0, 0, 0])
|
| 45 |
+
return {"occ": raw[..., :1], "xyz": self.centers[None] + raw[..., 1:4].tanh() / (2*self.grid),
|
| 46 |
+
"rgb": raw[..., 4:7].sigmoid(),
|
| 47 |
+
"scale": (raw[..., 7:10].clamp(-8, 5) - math.log(self.grid*3)).exp(),
|
| 48 |
+
"quat": F.normalize(quat, dim=-1, eps=1e-8), "opacity": raw[..., 14:15].sigmoid(),
|
| 49 |
+
"geometry": raw[..., 15:17]}
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def balanced_bce(logits, target):
|
| 53 |
+
error = F.binary_cross_entropy_with_logits(logits, target, reduction="none")
|
| 54 |
+
positive = (error * target).sum() / target.sum().clamp_min(1)
|
| 55 |
+
negative = (error * (1-target)).sum() / (1-target).sum().clamp_min(1)
|
| 56 |
+
return (positive + negative) / 2
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
def distillation_loss(pred, target, grid):
|
| 60 |
+
mask = target["occ"]
|
| 61 |
+
def masked(value):
|
| 62 |
+
return (value * mask).sum() / (mask.sum().clamp_min(1) * value.shape[-1])
|
| 63 |
+
terms = {"occupancy": balanced_bce(pred["occ"], mask),
|
| 64 |
+
"position": masked(((pred["xyz"] - target["xyz"]) * grid).square()),
|
| 65 |
+
"colour": masked((pred["rgb"] - target["rgb"].clamp(0, 1)).square()),
|
| 66 |
+
"scale": masked((pred["scale"].log() - target["scale"].clamp_min(1e-8).log()).square()),
|
| 67 |
+
"rotation": masked(1 - (pred["quat"] * target["quat"]).sum(-1, keepdim=True).square().clamp(0, 1)),
|
| 68 |
+
"opacity": masked((pred["opacity"] - target["opacity"]).square())}
|
| 69 |
+
geometry = pred["geometry"].sum() * 0
|
| 70 |
+
for i in range(2):
|
| 71 |
+
available = target["geometry_valid"][:, i] > 0
|
| 72 |
+
if available.any():
|
| 73 |
+
geometry = geometry + balanced_bce(pred["geometry"][available, :, i:i+1], target["geometry"][available, :, i:i+1])
|
| 74 |
+
terms["geometry"] = geometry
|
| 75 |
+
total = terms["occupancy"] + terms["position"] + 2*terms["colour"] + .1*terms["scale"] + .1*terms["rotation"] + terms["opacity"] + .25*geometry
|
| 76 |
+
return total, terms
|
src/image3d_student/splats.py
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
# Copyright 2026 Lucasgitguy-co
|
| 3 |
+
"""Activated Gaussian attributes and standard degree-zero 3DGS PLY IO.
|
| 4 |
+
|
| 5 |
+
Coordinates are preserved as supplied. Idol's *exported PLY* uses its y-up frame;
|
| 6 |
+
we do not apply Idol's internal z-up conversion a second time.
|
| 7 |
+
"""
|
| 8 |
+
from dataclasses import dataclass
|
| 9 |
+
from pathlib import Path
|
| 10 |
+
|
| 11 |
+
import numpy as np
|
| 12 |
+
from plyfile import PlyData, PlyElement
|
| 13 |
+
|
| 14 |
+
C0 = 0.28209479177387814
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
@dataclass
|
| 18 |
+
class Splats:
|
| 19 |
+
xyz: np.ndarray
|
| 20 |
+
rgb: np.ndarray
|
| 21 |
+
scale: np.ndarray
|
| 22 |
+
quat: np.ndarray # w,x,y,z
|
| 23 |
+
opacity: np.ndarray
|
| 24 |
+
|
| 25 |
+
def __post_init__(self):
|
| 26 |
+
n = len(self.xyz)
|
| 27 |
+
if n == 0:
|
| 28 |
+
raise ValueError("No Gaussians: refusing to write or train on an empty object.")
|
| 29 |
+
for name, width in [("xyz", 3), ("rgb", 3), ("scale", 3), ("quat", 4), ("opacity", 1)]:
|
| 30 |
+
a = np.asarray(getattr(self, name), dtype=np.float32).reshape(-1, width)
|
| 31 |
+
if a.shape != (n, width) or not np.isfinite(a).all():
|
| 32 |
+
raise ValueError(f"Invalid {name} shape or nonfinite values")
|
| 33 |
+
setattr(self, name, a)
|
| 34 |
+
if (self.scale <= 0).any():
|
| 35 |
+
raise ValueError("Gaussian scales must be positive")
|
| 36 |
+
if (self.opacity < 0).any() or (self.opacity > 1).any():
|
| 37 |
+
raise ValueError("Opacity must lie in [0,1]")
|
| 38 |
+
norm = np.linalg.norm(self.quat, axis=1, keepdims=True)
|
| 39 |
+
if (norm < 1e-8).any():
|
| 40 |
+
raise ValueError("Zero quaternion")
|
| 41 |
+
self.quat = self.quat / norm
|
| 42 |
+
|
| 43 |
+
def take(self, indices):
|
| 44 |
+
return Splats(**{k: getattr(self, k)[indices] for k in self.__dataclass_fields__})
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def read_ply(path):
|
| 48 |
+
v = PlyData.read(str(path))["vertex"].data
|
| 49 |
+
required = ["x", "y", "z", "f_dc_0", "f_dc_1", "f_dc_2", "opacity",
|
| 50 |
+
"scale_0", "scale_1", "scale_2", "rot_0", "rot_1", "rot_2", "rot_3"]
|
| 51 |
+
if not set(required).issubset(v.dtype.names):
|
| 52 |
+
raise ValueError("Expected a Gaussian-splat PLY, not a mesh or ordinary point-cloud PLY")
|
| 53 |
+
col = lambda names: np.column_stack([v[k] for k in names]).astype(np.float32)
|
| 54 |
+
return Splats(col(["x", "y", "z"]), 0.5 + C0 * col([f"f_dc_{i}" for i in range(3)]),
|
| 55 |
+
np.exp(np.clip(col([f"scale_{i}" for i in range(3)]), -20, 5)),
|
| 56 |
+
col([f"rot_{i}" for i in range(4)]),
|
| 57 |
+
1 / (1 + np.exp(-np.clip(col(["opacity"]), -30, 30))))
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def write_ply(path, splats):
|
| 61 |
+
path = Path(path)
|
| 62 |
+
path.parent.mkdir(parents=True, exist_ok=True)
|
| 63 |
+
names = ["x", "y", "z", "nx", "ny", "nz", "f_dc_0", "f_dc_1", "f_dc_2", "opacity",
|
| 64 |
+
"scale_0", "scale_1", "scale_2", "rot_0", "rot_1", "rot_2", "rot_3"]
|
| 65 |
+
opacity = np.clip(splats.opacity, 1e-6, 1 - 1e-6)
|
| 66 |
+
values = np.concatenate([splats.xyz, np.zeros_like(splats.xyz), (splats.rgb - 0.5) / C0,
|
| 67 |
+
np.log(opacity / (1 - opacity)), np.log(splats.scale), splats.quat], axis=1)
|
| 68 |
+
table = np.empty(len(values), dtype=[(k, "f4") for k in names])
|
| 69 |
+
for i, name in enumerate(names):
|
| 70 |
+
table[name] = values[:, i]
|
| 71 |
+
PlyData([PlyElement.describe(table, "vertex")], text=False).write(str(path))
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
def rotation_matrices(q):
|
| 75 |
+
w, x, y, z = q.T
|
| 76 |
+
return np.stack([1-2*(y*y+z*z), 2*(x*y-z*w), 2*(x*z+y*w),
|
| 77 |
+
2*(x*y+z*w), 1-2*(x*x+z*z), 2*(y*z-x*w),
|
| 78 |
+
2*(x*z-y*w), 2*(y*z+x*w), 1-2*(x*x+y*y)], axis=-1).reshape(-1, 3, 3)
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def preview(splats, size=256, yaw=0.0):
|
| 82 |
+
"""CPU orthographic Gaussian preview; debugging only, not an evaluation renderer."""
|
| 83 |
+
from PIL import Image
|
| 84 |
+
c, s = np.cos(yaw), np.sin(yaw)
|
| 85 |
+
view = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]], dtype=np.float32)
|
| 86 |
+
xyz = splats.xyz @ view.T
|
| 87 |
+
rot = rotation_matrices(splats.quat)
|
| 88 |
+
cov = (rot * (splats.scale ** 2)[:, None, :]) @ rot.transpose(0, 2, 1)
|
| 89 |
+
cov = view[None] @ cov @ view.T[None]
|
| 90 |
+
pixels = size / 1.25
|
| 91 |
+
canvas = np.zeros((size, size, 3), dtype=np.float32)
|
| 92 |
+
# Back to front, camera on +z. Image y points down.
|
| 93 |
+
for i in np.argsort(xyz[:, 2]):
|
| 94 |
+
center = np.array([xyz[i, 0], -xyz[i, 1]]) * pixels + size / 2
|
| 95 |
+
flip = np.diag([1., -1.])
|
| 96 |
+
covariance = flip @ cov[i, :2, :2] @ flip * pixels ** 2 + np.eye(2) * 0.3
|
| 97 |
+
radius = min(size, int(np.ceil(3 * np.sqrt(np.linalg.eigvalsh(covariance).max()))))
|
| 98 |
+
lo = np.maximum(0, np.floor(center - radius).astype(int))
|
| 99 |
+
hi = np.minimum(size, np.ceil(center + radius + 1).astype(int))
|
| 100 |
+
if np.any(hi <= lo):
|
| 101 |
+
continue
|
| 102 |
+
yy, xx = np.mgrid[lo[1]:hi[1], lo[0]:hi[0]]
|
| 103 |
+
delta = np.stack([xx - center[0], yy - center[1]], axis=-1)
|
| 104 |
+
exponent = np.einsum("...i,ij,...j->...", delta, np.linalg.inv(covariance), delta)
|
| 105 |
+
alpha = (splats.opacity[i, 0] * np.exp(-0.5 * exponent)).clip(0, .99)[..., None]
|
| 106 |
+
patch = canvas[lo[1]:hi[1], lo[0]:hi[0]]
|
| 107 |
+
patch[:] = patch * (1-alpha) + np.clip(splats.rgb[i], 0, 1) * alpha
|
| 108 |
+
return Image.fromarray((canvas.clip(0, 1) * 255).astype(np.uint8))
|
src/image3d_student/teacher_idol.py
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
# Copyright 2026 Lucasgitguy-co
|
| 3 |
+
"""Experimental, staged Idol inference for Apple MPS.
|
| 4 |
+
|
| 5 |
+
Upstream revision: 4702a7f00850e34b6e83a2170cc123c3e9570744.
|
| 6 |
+
No weights are bundled. Full-weight inference has NOT been verified by this project.
|
| 7 |
+
"""
|
| 8 |
+
import gc
|
| 9 |
+
import json
|
| 10 |
+
import os
|
| 11 |
+
import shutil
|
| 12 |
+
from pathlib import Path
|
| 13 |
+
|
| 14 |
+
import numpy as np
|
| 15 |
+
import torch
|
| 16 |
+
from PIL import Image
|
| 17 |
+
|
| 18 |
+
from .engine import device_for
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def patch_attention(layers, query_chunk=128):
|
| 22 |
+
"""Bound attention working memory by splitting only the query dimension.
|
| 23 |
+
|
| 24 |
+
Each query still sees ALL keys/values. Does not split or change softmax's key axis.
|
| 25 |
+
Disable CUDA-specific optimized sampling and avoid complex RoPE tensors on MPS.
|
| 26 |
+
"""
|
| 27 |
+
if query_chunk < 1:
|
| 28 |
+
raise ValueError("query_chunk must be positive")
|
| 29 |
+
from torch.nn import functional as F
|
| 30 |
+
|
| 31 |
+
def attention(*args):
|
| 32 |
+
q, k, v = args[0].unbind(dim=2) if len(args) == 1 else args
|
| 33 |
+
q, k, v = (t.permute(0, 2, 1, 3) for t in (q, k, v))
|
| 34 |
+
chunks = [F.scaled_dot_product_attention(q[:, :, start:start+query_chunk], k, v)
|
| 35 |
+
for start in range(0, q.shape[2], query_chunk)]
|
| 36 |
+
return torch.cat(chunks, dim=2).permute(0, 2, 1, 3)
|
| 37 |
+
|
| 38 |
+
layers.scaled_dot_product_attention = attention
|
| 39 |
+
layers.RePo3DRotaryEmbedding.real_valued = True
|
| 40 |
+
return attention
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
def release(device):
|
| 44 |
+
gc.collect()
|
| 45 |
+
if device.type == "mps":
|
| 46 |
+
torch.mps.synchronize()
|
| 47 |
+
torch.mps.empty_cache()
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
@torch.no_grad()
|
| 51 |
+
def run_idol(args):
|
| 52 |
+
if args.steps < 1 or args.gaussians < 32768 or args.gaussians > 1048576 or args.gaussians % 32:
|
| 53 |
+
raise ValueError("Steps must be positive; Idol requires 32768..1048576 Gaussians, divisible by 32")
|
| 54 |
+
device = device_for(args.device)
|
| 55 |
+
cache = Path(args.cache).resolve()
|
| 56 |
+
cache.mkdir(parents=True, exist_ok=True)
|
| 57 |
+
os.environ["HF_HOME"] = str(cache)
|
| 58 |
+
os.environ["HF_HUB_OFFLINE"] = "0" if args.allow_download else "1"
|
| 59 |
+
os.environ["ATTN_BACKEND"] = "sdpa"
|
| 60 |
+
if args.allow_download and shutil.disk_usage(cache).free < 16 * 1024**3:
|
| 61 |
+
raise ValueError("Less than 16 GiB disk space available. This conservative download guard leaves room for teacher weights, encoders and temporary files. Free space, or use an existing complete cache without --allow-download.")
|
| 62 |
+
try:
|
| 63 |
+
from huggingface_hub import hf_hub_download, snapshot_download
|
| 64 |
+
from safetensors.torch import load_file
|
| 65 |
+
from tensordict import TensorDict
|
| 66 |
+
from idol.conditioning import ImageEncoder, require_encoder_access
|
| 67 |
+
from idol.models import BiRefNet, GaussianFixedlenDecoder, LatentSeqMMFlowModel, OctreeProbabilityFixedlenDecoder, layers
|
| 68 |
+
from idol.preprocess import CROP_MARGIN, preprocess_image, has_real_alpha
|
| 69 |
+
from idol.sampler import sample_flow
|
| 70 |
+
from idol.camera import decode_camera
|
| 71 |
+
except ImportError as exc:
|
| 72 |
+
raise RuntimeError("Install the optional teacher dependencies: python -m pip install '.[teacher]'") from exc
|
| 73 |
+
out = Path(args.out)
|
| 74 |
+
if out.exists():
|
| 75 |
+
raise ValueError("Teacher output directory already exists; choose a new --out")
|
| 76 |
+
# Local-only by default. Hugging Face authentication is never written to project files.
|
| 77 |
+
config_path = hf_hub_download(args.weights, "config.json", local_files_only=not args.allow_download)
|
| 78 |
+
config = json.loads(Path(config_path).read_text())
|
| 79 |
+
encoders = config["image_encoders"]
|
| 80 |
+
require_encoder_access([encoders["dinov3"], encoders["flux2_vae"]])
|
| 81 |
+
weights = Path(snapshot_download(args.weights, allow_patterns=["config.json", "*.safetensors"],
|
| 82 |
+
local_files_only=not args.allow_download))
|
| 83 |
+
patch_attention(layers, args.query_chunk)
|
| 84 |
+
torch.manual_seed(args.seed)
|
| 85 |
+
|
| 86 |
+
def load(model, name):
|
| 87 |
+
state = load_file(str(weights / f"{name}.safetensors"), device="cpu")
|
| 88 |
+
model.load_state_dict(state, strict=True)
|
| 89 |
+
del state
|
| 90 |
+
return model.eval().requires_grad_(False).to(device)
|
| 91 |
+
|
| 92 |
+
print("Experimental Idol MPS adapter: full-weight compatibility and quality remain unverified.", flush=True)
|
| 93 |
+
with Image.open(args.image) as opened:
|
| 94 |
+
image = opened.copy()
|
| 95 |
+
background = None
|
| 96 |
+
if not has_real_alpha(image):
|
| 97 |
+
print("Stage 1: background removal", flush=True)
|
| 98 |
+
background = load(BiRefNet(), "birefnet")
|
| 99 |
+
prepared = preprocess_image(image, background, config["image_size"], CROP_MARGIN[args.mode])
|
| 100 |
+
del background
|
| 101 |
+
release(device)
|
| 102 |
+
pixels = torch.from_numpy(np.array(prepared)).permute(2, 0, 1).float()[None].div(255).to(device)
|
| 103 |
+
print("Stage 2: image conditioning", flush=True)
|
| 104 |
+
encoder = ImageEncoder(encoders["dinov3"], encoders["flux2_vae"], device="cpu")
|
| 105 |
+
# Both encoders initially reside on CPU; only the active encoder is moved to MPS.
|
| 106 |
+
encoder.dinov3.to(device)
|
| 107 |
+
feature1 = encoder._dinov3_tokens(pixels)
|
| 108 |
+
del encoder.dinov3
|
| 109 |
+
release(device)
|
| 110 |
+
encoder.flux2_vae.to(device)
|
| 111 |
+
feature2 = encoder._flux2_tokens(pixels)
|
| 112 |
+
del encoder, pixels
|
| 113 |
+
release(device)
|
| 114 |
+
cond = TensorDict({"feature1": feature1, "feature2": feature2}, batch_size=1, device=device)
|
| 115 |
+
print("Stage 3: latent sampling", flush=True)
|
| 116 |
+
model = load(LatentSeqMMFlowModel(**config["denoiser"]["args"]), "denoiser")
|
| 117 |
+
noise = TensorDict({"latent": torch.randn(1, model.q_token_length, model.in_channels, device=device),
|
| 118 |
+
"camera": torch.randn(1, 1, model.cam_channels, device=device)}, batch_size=1, device=device)
|
| 119 |
+
result = sample_flow(model, noise, cond=cond, neg_cond=cond.apply(torch.zeros_like), steps=args.steps,
|
| 120 |
+
rescale_t=3., cfg_strength=3., verbose=True, batch_cfg=False)
|
| 121 |
+
latent, camera = result["latent"], decode_camera(result["camera"][0, 0])
|
| 122 |
+
del model, noise, cond, feature1, feature2, result
|
| 123 |
+
release(device)
|
| 124 |
+
print("Stage 4: octree decoding", flush=True)
|
| 125 |
+
model = load(OctreeProbabilityFixedlenDecoder(**config["decoder"]["args"]), "decoder")
|
| 126 |
+
per_anchor = config["decoder_gs"]["args"]["representation_config"]["num_gaussians"]
|
| 127 |
+
anchors = OctreeProbabilityFixedlenDecoder.sample(model, latent, num_points=args.gaussians // per_anchor,
|
| 128 |
+
level=config["max_voxel_level"])
|
| 129 |
+
del model
|
| 130 |
+
release(device)
|
| 131 |
+
print("Stage 5: Gaussian decoding", flush=True)
|
| 132 |
+
model = load(GaussianFixedlenDecoder(**config["decoder_gs"]["args"]), "decoder_gs")
|
| 133 |
+
gaussian = model.to_representation(anchors, model(anchors, latent))[0]
|
| 134 |
+
out.mkdir(parents=True)
|
| 135 |
+
gaussian.save_ply(str(out / "teacher.ply"))
|
| 136 |
+
prepared.save(out / "input.png")
|
| 137 |
+
(out / "metadata.json").write_text(json.dumps({"teacher": args.weights, "steps": args.steps,
|
| 138 |
+
"gaussians": args.gaussians, "seed": args.seed, "device": str(device), "camera": camera,
|
| 139 |
+
"sdk_revision": "4702a7f00850e34b6e83a2170cc123c3e9570744", "weights_snapshot": weights.name,
|
| 140 |
+
"coordinate_frame": "Idol exported PLY (y-up)", "adapter": "experimental staged MPS"}, indent=2))
|
| 141 |
+
print(f"Teacher output saved to {out}", flush=True)
|
train-mac.sh
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
set -euo pipefail
|
| 3 |
+
cd "$(dirname "$0")"
|
| 4 |
+
if [[ "${1:-}" != "--publish" && -n "${1:-}" ]]; then
|
| 5 |
+
echo 'Usage: bash train-mac.sh [--publish]' >&2
|
| 6 |
+
exit 2
|
| 7 |
+
fi
|
| 8 |
+
FORMA3D_RUNTIME_DIR="${FORMA3D_RUNTIME_DIR:-$HOME/Library/Application Support/Forma3D}"
|
| 9 |
+
FORMA3D_PYTHON="$FORMA3D_RUNTIME_DIR/venv/bin/python"
|
| 10 |
+
if [[ ! -x "$FORMA3D_PYTHON" ]]; then
|
| 11 |
+
bash setup-mac.sh
|
| 12 |
+
fi
|
| 13 |
+
# Never depend on the caller's PATH, aliases, activation, or editable .pth files.
|
| 14 |
+
"$FORMA3D_PYTHON" -m image3d_student.cli doctor
|
| 15 |
+
if [[ ! -f base/examples/synthetic-smoke/synthetic-only.pt ]]; then
|
| 16 |
+
"$FORMA3D_RUNTIME_DIR/venv/bin/hf" download Lucasgitguy-co/image3d-student \
|
| 17 |
+
examples/synthetic-smoke/synthetic-only.pt \
|
| 18 |
+
--revision 1738cdfaf1bb940bf576a96d11b742ce014b9139 --local-dir base
|
| 19 |
+
fi
|
| 20 |
+
"$FORMA3D_PYTHON" - <<'PY'
|
| 21 |
+
from pathlib import Path
|
| 22 |
+
import hashlib
|
| 23 |
+
path = Path("base/examples/synthetic-smoke/synthetic-only.pt")
|
| 24 |
+
expected = "dd1a1719541c5603125e7f9379b0ad8ede20b7e9f2816a04e9120244cdbf528e"
|
| 25 |
+
if hashlib.sha256(path.read_bytes()).hexdigest() != expected:
|
| 26 |
+
raise SystemExit("Base checkpoint checksum mismatch; restore the pinned original checkpoint.")
|
| 27 |
+
print("Verified local base checkpoint; no Hugging Face connection required for training.")
|
| 28 |
+
PY
|
| 29 |
+
if [[ -s data/forma3d-v1/manifest.jsonl && -s data/forma3d-v1/test-manifest.jsonl ]]; then
|
| 30 |
+
echo 'Using completed dataset. Training will verify the cached sample hashes.'
|
| 31 |
+
else
|
| 32 |
+
"$FORMA3D_PYTHON" scripts/prepare_hf.py --out data/forma3d-v1 --cache data/downloads \
|
| 33 |
+
--scenario 64 --objaverse 32 --objaverse-shards 8 --grid 16 --views 4 --resume \
|
| 34 |
+
--max-file-mb 16 --max-download-mb 2048
|
| 35 |
+
fi
|
| 36 |
+
"$FORMA3D_PYTHON" -m image3d_student.cli train --manifest data/forma3d-v1/manifest.jsonl \
|
| 37 |
+
--init-from base/examples/synthetic-smoke/synthetic-only.pt \
|
| 38 |
+
--out runs/forma3d-v1 --device mps --width 64 --steps 5000 \
|
| 39 |
+
--batch-size 2 --lr 0.0001 --eval-every 100 --validation-fraction 0.2 --seed 42
|
| 40 |
+
if [[ "${1:-}" == "--publish" ]]; then set -- --publish; else set --; fi
|
| 41 |
+
"$FORMA3D_PYTHON" scripts/release.py --run runs/forma3d-v1 --data data/forma3d-v1 \
|
| 42 |
+
--base base/examples/synthetic-smoke/synthetic-only.pt \
|
| 43 |
+
--release release/forma3d-v1 --device mps --repo Lucasgitguy-co/forma3d-tiny \
|
| 44 |
+
"$@"
|
training.json
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"synthetic_only": false,
|
| 3 |
+
"contains_synthetic": false,
|
| 4 |
+
"device": "mps",
|
| 5 |
+
"torch": "2.15.0",
|
| 6 |
+
"seed": 42,
|
| 7 |
+
"train_ids": [
|
| 8 |
+
"e72c70c3a1e70f61edd5-v0",
|
| 9 |
+
"e72c70c3a1e70f61edd5-v1",
|
| 10 |
+
"e72c70c3a1e70f61edd5-v2",
|
| 11 |
+
"e72c70c3a1e70f61edd5-v3",
|
| 12 |
+
"0d291e312da4267be597-v0",
|
| 13 |
+
"0d291e312da4267be597-v1",
|
| 14 |
+
"0d291e312da4267be597-v2",
|
| 15 |
+
"0d291e312da4267be597-v3",
|
| 16 |
+
"84e4d421b6e5a54babac-v0",
|
| 17 |
+
"84e4d421b6e5a54babac-v1",
|
| 18 |
+
"84e4d421b6e5a54babac-v2",
|
| 19 |
+
"84e4d421b6e5a54babac-v3",
|
| 20 |
+
"f008965c2682f5284b4a-v0",
|
| 21 |
+
"f008965c2682f5284b4a-v1",
|
| 22 |
+
"f008965c2682f5284b4a-v2",
|
| 23 |
+
"f008965c2682f5284b4a-v3",
|
| 24 |
+
"01a7f40607c8cc615f61-v0",
|
| 25 |
+
"01a7f40607c8cc615f61-v1",
|
| 26 |
+
"01a7f40607c8cc615f61-v2",
|
| 27 |
+
"01a7f40607c8cc615f61-v3",
|
| 28 |
+
"f09b694a85d9fb4ae019-v0",
|
| 29 |
+
"f09b694a85d9fb4ae019-v1",
|
| 30 |
+
"f09b694a85d9fb4ae019-v2",
|
| 31 |
+
"f09b694a85d9fb4ae019-v3",
|
| 32 |
+
"e6c0c457e7b31561c451-v0",
|
| 33 |
+
"e6c0c457e7b31561c451-v1",
|
| 34 |
+
"e6c0c457e7b31561c451-v2",
|
| 35 |
+
"e6c0c457e7b31561c451-v3",
|
| 36 |
+
"78896f0abf8077250b90-v0",
|
| 37 |
+
"78896f0abf8077250b90-v1",
|
| 38 |
+
"78896f0abf8077250b90-v2",
|
| 39 |
+
"78896f0abf8077250b90-v3",
|
| 40 |
+
"b46a1c9864cb8b45fbe3-v0",
|
| 41 |
+
"b46a1c9864cb8b45fbe3-v1",
|
| 42 |
+
"b46a1c9864cb8b45fbe3-v2",
|
| 43 |
+
"b46a1c9864cb8b45fbe3-v3",
|
| 44 |
+
"6aaedee39b80ba8b7189-v0",
|
| 45 |
+
"6aaedee39b80ba8b7189-v1",
|
| 46 |
+
"6aaedee39b80ba8b7189-v2",
|
| 47 |
+
"6aaedee39b80ba8b7189-v3",
|
| 48 |
+
"acb330462014e2d1fadf-v0",
|
| 49 |
+
"acb330462014e2d1fadf-v1",
|
| 50 |
+
"acb330462014e2d1fadf-v2",
|
| 51 |
+
"acb330462014e2d1fadf-v3",
|
| 52 |
+
"506f7b7a7c46bcbd7b3d-v0",
|
| 53 |
+
"506f7b7a7c46bcbd7b3d-v1",
|
| 54 |
+
"506f7b7a7c46bcbd7b3d-v2",
|
| 55 |
+
"506f7b7a7c46bcbd7b3d-v3",
|
| 56 |
+
"877b14c0a003ed864972-v0",
|
| 57 |
+
"877b14c0a003ed864972-v1",
|
| 58 |
+
"877b14c0a003ed864972-v2",
|
| 59 |
+
"877b14c0a003ed864972-v3",
|
| 60 |
+
"d98b7eab417645c408d5-v0",
|
| 61 |
+
"d98b7eab417645c408d5-v1",
|
| 62 |
+
"d98b7eab417645c408d5-v2",
|
| 63 |
+
"d98b7eab417645c408d5-v3",
|
| 64 |
+
"767aff69879484e9b54b-v0",
|
| 65 |
+
"767aff69879484e9b54b-v1",
|
| 66 |
+
"767aff69879484e9b54b-v2",
|
| 67 |
+
"767aff69879484e9b54b-v3",
|
| 68 |
+
"3a307f409ee3c0236ccf-v0",
|
| 69 |
+
"3a307f409ee3c0236ccf-v1",
|
| 70 |
+
"3a307f409ee3c0236ccf-v2",
|
| 71 |
+
"3a307f409ee3c0236ccf-v3",
|
| 72 |
+
"e9848ffcaeb4bae99e2f-v0",
|
| 73 |
+
"e9848ffcaeb4bae99e2f-v1",
|
| 74 |
+
"e9848ffcaeb4bae99e2f-v2",
|
| 75 |
+
"e9848ffcaeb4bae99e2f-v3",
|
| 76 |
+
"f54650801d02e5d43e10-v0",
|
| 77 |
+
"f54650801d02e5d43e10-v1",
|
| 78 |
+
"f54650801d02e5d43e10-v2",
|
| 79 |
+
"f54650801d02e5d43e10-v3",
|
| 80 |
+
"892e464cf207e7425400-v0",
|
| 81 |
+
"892e464cf207e7425400-v1",
|
| 82 |
+
"892e464cf207e7425400-v2",
|
| 83 |
+
"892e464cf207e7425400-v3",
|
| 84 |
+
"6b56e16d01faf9b952a4-v0",
|
| 85 |
+
"6b56e16d01faf9b952a4-v1",
|
| 86 |
+
"6b56e16d01faf9b952a4-v2",
|
| 87 |
+
"6b56e16d01faf9b952a4-v3",
|
| 88 |
+
"ff4bcdb48f7a73ce8f21-v0",
|
| 89 |
+
"ff4bcdb48f7a73ce8f21-v1",
|
| 90 |
+
"ff4bcdb48f7a73ce8f21-v2",
|
| 91 |
+
"ff4bcdb48f7a73ce8f21-v3",
|
| 92 |
+
"39a959b3abba0a20445f-v0",
|
| 93 |
+
"39a959b3abba0a20445f-v1",
|
| 94 |
+
"39a959b3abba0a20445f-v2",
|
| 95 |
+
"39a959b3abba0a20445f-v3",
|
| 96 |
+
"487ec3573a2ca1585f1d-v0",
|
| 97 |
+
"487ec3573a2ca1585f1d-v1",
|
| 98 |
+
"487ec3573a2ca1585f1d-v2",
|
| 99 |
+
"487ec3573a2ca1585f1d-v3",
|
| 100 |
+
"4110e3fcc9c9692aebb0-v0",
|
| 101 |
+
"4110e3fcc9c9692aebb0-v1",
|
| 102 |
+
"4110e3fcc9c9692aebb0-v2",
|
| 103 |
+
"4110e3fcc9c9692aebb0-v3",
|
| 104 |
+
"91b9e1671c9f2fa0c94d-v0",
|
| 105 |
+
"91b9e1671c9f2fa0c94d-v1",
|
| 106 |
+
"91b9e1671c9f2fa0c94d-v2",
|
| 107 |
+
"91b9e1671c9f2fa0c94d-v3",
|
| 108 |
+
"ffd52f05142cacd19926-v0",
|
| 109 |
+
"ffd52f05142cacd19926-v1",
|
| 110 |
+
"ffd52f05142cacd19926-v2",
|
| 111 |
+
"ffd52f05142cacd19926-v3",
|
| 112 |
+
"a7b178ca7586f58d4097-v0",
|
| 113 |
+
"a7b178ca7586f58d4097-v1",
|
| 114 |
+
"a7b178ca7586f58d4097-v2",
|
| 115 |
+
"a7b178ca7586f58d4097-v3",
|
| 116 |
+
"e70b599ffd981c2bc6e4-v0",
|
| 117 |
+
"e70b599ffd981c2bc6e4-v1",
|
| 118 |
+
"e70b599ffd981c2bc6e4-v2",
|
| 119 |
+
"e70b599ffd981c2bc6e4-v3",
|
| 120 |
+
"d73e287e1bdffce35b5e-v0",
|
| 121 |
+
"d73e287e1bdffce35b5e-v1",
|
| 122 |
+
"d73e287e1bdffce35b5e-v2",
|
| 123 |
+
"d73e287e1bdffce35b5e-v3",
|
| 124 |
+
"479fa0112556943251d3-v0",
|
| 125 |
+
"479fa0112556943251d3-v1",
|
| 126 |
+
"479fa0112556943251d3-v2",
|
| 127 |
+
"479fa0112556943251d3-v3",
|
| 128 |
+
"d565ef67b0f63a87fbd1-v0",
|
| 129 |
+
"d565ef67b0f63a87fbd1-v1",
|
| 130 |
+
"d565ef67b0f63a87fbd1-v2",
|
| 131 |
+
"d565ef67b0f63a87fbd1-v3",
|
| 132 |
+
"dba4d5ea99b771567e65-v0",
|
| 133 |
+
"dba4d5ea99b771567e65-v1",
|
| 134 |
+
"dba4d5ea99b771567e65-v2",
|
| 135 |
+
"dba4d5ea99b771567e65-v3",
|
| 136 |
+
"1991d8540d749adbd5a2-v0",
|
| 137 |
+
"1991d8540d749adbd5a2-v1",
|
| 138 |
+
"1991d8540d749adbd5a2-v2",
|
| 139 |
+
"1991d8540d749adbd5a2-v3",
|
| 140 |
+
"d3d0a3244bfbbecb7a81-v0",
|
| 141 |
+
"d3d0a3244bfbbecb7a81-v1",
|
| 142 |
+
"d3d0a3244bfbbecb7a81-v2",
|
| 143 |
+
"d3d0a3244bfbbecb7a81-v3",
|
| 144 |
+
"ad38410cc4305837cdb5-v0",
|
| 145 |
+
"ad38410cc4305837cdb5-v1",
|
| 146 |
+
"ad38410cc4305837cdb5-v2",
|
| 147 |
+
"ad38410cc4305837cdb5-v3",
|
| 148 |
+
"ebb51cc1980b817b5293-v0",
|
| 149 |
+
"ebb51cc1980b817b5293-v1",
|
| 150 |
+
"ebb51cc1980b817b5293-v2",
|
| 151 |
+
"ebb51cc1980b817b5293-v3",
|
| 152 |
+
"d0528548ab492ec49c9a-v0",
|
| 153 |
+
"d0528548ab492ec49c9a-v1",
|
| 154 |
+
"d0528548ab492ec49c9a-v2",
|
| 155 |
+
"d0528548ab492ec49c9a-v3",
|
| 156 |
+
"fdca1c9444afdf164314-v0",
|
| 157 |
+
"fdca1c9444afdf164314-v1",
|
| 158 |
+
"fdca1c9444afdf164314-v2",
|
| 159 |
+
"fdca1c9444afdf164314-v3",
|
| 160 |
+
"e507f81099340e7731c1-v0",
|
| 161 |
+
"e507f81099340e7731c1-v1",
|
| 162 |
+
"e507f81099340e7731c1-v2",
|
| 163 |
+
"e507f81099340e7731c1-v3",
|
| 164 |
+
"e359f477410745cb90bd-v0",
|
| 165 |
+
"e359f477410745cb90bd-v1",
|
| 166 |
+
"e359f477410745cb90bd-v2",
|
| 167 |
+
"e359f477410745cb90bd-v3",
|
| 168 |
+
"f6f8dfa58f3a7ee4a6ce-v0",
|
| 169 |
+
"f6f8dfa58f3a7ee4a6ce-v1",
|
| 170 |
+
"f6f8dfa58f3a7ee4a6ce-v2",
|
| 171 |
+
"f6f8dfa58f3a7ee4a6ce-v3",
|
| 172 |
+
"980b32fad9f17c74634e-v0",
|
| 173 |
+
"980b32fad9f17c74634e-v1",
|
| 174 |
+
"980b32fad9f17c74634e-v2",
|
| 175 |
+
"980b32fad9f17c74634e-v3",
|
| 176 |
+
"de616e5af2ae654855de-v0",
|
| 177 |
+
"de616e5af2ae654855de-v1",
|
| 178 |
+
"de616e5af2ae654855de-v2",
|
| 179 |
+
"de616e5af2ae654855de-v3",
|
| 180 |
+
"39ff027ad9a68325c378-v0",
|
| 181 |
+
"39ff027ad9a68325c378-v1",
|
| 182 |
+
"39ff027ad9a68325c378-v2",
|
| 183 |
+
"39ff027ad9a68325c378-v3",
|
| 184 |
+
"40a403b1f00a7731bb0c-v0",
|
| 185 |
+
"40a403b1f00a7731bb0c-v1",
|
| 186 |
+
"40a403b1f00a7731bb0c-v2",
|
| 187 |
+
"40a403b1f00a7731bb0c-v3",
|
| 188 |
+
"79432b2b1f925ac322aa-v0",
|
| 189 |
+
"79432b2b1f925ac322aa-v1",
|
| 190 |
+
"79432b2b1f925ac322aa-v2",
|
| 191 |
+
"79432b2b1f925ac322aa-v3",
|
| 192 |
+
"49aa39b4083329b974a3-v0",
|
| 193 |
+
"49aa39b4083329b974a3-v1",
|
| 194 |
+
"49aa39b4083329b974a3-v2",
|
| 195 |
+
"49aa39b4083329b974a3-v3",
|
| 196 |
+
"2cea1c878a4547ece95e-v0",
|
| 197 |
+
"2cea1c878a4547ece95e-v1",
|
| 198 |
+
"2cea1c878a4547ece95e-v2",
|
| 199 |
+
"2cea1c878a4547ece95e-v3",
|
| 200 |
+
"07290c65376571fc88e3-v0",
|
| 201 |
+
"07290c65376571fc88e3-v1",
|
| 202 |
+
"07290c65376571fc88e3-v2",
|
| 203 |
+
"07290c65376571fc88e3-v3",
|
| 204 |
+
"b33aeb679195ac416fd9-v0",
|
| 205 |
+
"b33aeb679195ac416fd9-v1",
|
| 206 |
+
"b33aeb679195ac416fd9-v2",
|
| 207 |
+
"b33aeb679195ac416fd9-v3",
|
| 208 |
+
"50762ad6529b83e23d3e-v0",
|
| 209 |
+
"50762ad6529b83e23d3e-v1",
|
| 210 |
+
"50762ad6529b83e23d3e-v2",
|
| 211 |
+
"50762ad6529b83e23d3e-v3",
|
| 212 |
+
"1497430051592337cdfc-v0",
|
| 213 |
+
"1497430051592337cdfc-v1",
|
| 214 |
+
"1497430051592337cdfc-v2",
|
| 215 |
+
"1497430051592337cdfc-v3",
|
| 216 |
+
"b12004dfbec10d17137b-v0",
|
| 217 |
+
"b12004dfbec10d17137b-v1",
|
| 218 |
+
"b12004dfbec10d17137b-v2",
|
| 219 |
+
"b12004dfbec10d17137b-v3",
|
| 220 |
+
"7fec3c65a68dbe7758fd-v0",
|
| 221 |
+
"7fec3c65a68dbe7758fd-v1",
|
| 222 |
+
"7fec3c65a68dbe7758fd-v2",
|
| 223 |
+
"7fec3c65a68dbe7758fd-v3",
|
| 224 |
+
"54da5dddde1e0361afec-v0",
|
| 225 |
+
"54da5dddde1e0361afec-v1",
|
| 226 |
+
"54da5dddde1e0361afec-v2",
|
| 227 |
+
"54da5dddde1e0361afec-v3",
|
| 228 |
+
"38cbe4583d4af82bc1cc-v0",
|
| 229 |
+
"38cbe4583d4af82bc1cc-v1",
|
| 230 |
+
"38cbe4583d4af82bc1cc-v2",
|
| 231 |
+
"38cbe4583d4af82bc1cc-v3",
|
| 232 |
+
"07e668758676dbec5048-v0",
|
| 233 |
+
"07e668758676dbec5048-v1",
|
| 234 |
+
"07e668758676dbec5048-v2",
|
| 235 |
+
"07e668758676dbec5048-v3",
|
| 236 |
+
"f7c40d2912c6461a63a2-v0",
|
| 237 |
+
"f7c40d2912c6461a63a2-v1",
|
| 238 |
+
"f7c40d2912c6461a63a2-v2",
|
| 239 |
+
"f7c40d2912c6461a63a2-v3",
|
| 240 |
+
"9c91b0b9762c72ffb714-v0",
|
| 241 |
+
"9c91b0b9762c72ffb714-v1",
|
| 242 |
+
"9c91b0b9762c72ffb714-v2",
|
| 243 |
+
"9c91b0b9762c72ffb714-v3",
|
| 244 |
+
"8c360413890122153c7c-v0",
|
| 245 |
+
"8c360413890122153c7c-v1",
|
| 246 |
+
"8c360413890122153c7c-v2",
|
| 247 |
+
"8c360413890122153c7c-v3",
|
| 248 |
+
"7d76a5fc01ddbc5f5382-v0",
|
| 249 |
+
"7d76a5fc01ddbc5f5382-v1",
|
| 250 |
+
"7d76a5fc01ddbc5f5382-v2",
|
| 251 |
+
"7d76a5fc01ddbc5f5382-v3",
|
| 252 |
+
"95b2b7b5a0e29c6551d5-v0",
|
| 253 |
+
"95b2b7b5a0e29c6551d5-v1",
|
| 254 |
+
"95b2b7b5a0e29c6551d5-v2",
|
| 255 |
+
"95b2b7b5a0e29c6551d5-v3",
|
| 256 |
+
"eea38754ae954df09aec-v0",
|
| 257 |
+
"eea38754ae954df09aec-v1",
|
| 258 |
+
"eea38754ae954df09aec-v2",
|
| 259 |
+
"eea38754ae954df09aec-v3",
|
| 260 |
+
"ae721d3ddbeb66f2a3bb-v0",
|
| 261 |
+
"ae721d3ddbeb66f2a3bb-v1",
|
| 262 |
+
"ae721d3ddbeb66f2a3bb-v2",
|
| 263 |
+
"ae721d3ddbeb66f2a3bb-v3",
|
| 264 |
+
"30ee3daeaecfc3ecc40b-v0",
|
| 265 |
+
"30ee3daeaecfc3ecc40b-v1",
|
| 266 |
+
"30ee3daeaecfc3ecc40b-v2",
|
| 267 |
+
"30ee3daeaecfc3ecc40b-v3"
|
| 268 |
+
],
|
| 269 |
+
"val_ids": [
|
| 270 |
+
"478e3ebcd3a9761cc58d-v0",
|
| 271 |
+
"478e3ebcd3a9761cc58d-v1",
|
| 272 |
+
"478e3ebcd3a9761cc58d-v2",
|
| 273 |
+
"478e3ebcd3a9761cc58d-v3",
|
| 274 |
+
"3cccc2387af01902fa18-v0",
|
| 275 |
+
"3cccc2387af01902fa18-v1",
|
| 276 |
+
"3cccc2387af01902fa18-v2",
|
| 277 |
+
"3cccc2387af01902fa18-v3",
|
| 278 |
+
"2d390b9a71cd4246f2a6-v0",
|
| 279 |
+
"2d390b9a71cd4246f2a6-v1",
|
| 280 |
+
"2d390b9a71cd4246f2a6-v2",
|
| 281 |
+
"2d390b9a71cd4246f2a6-v3",
|
| 282 |
+
"d35f5efca2a60d63c4b6-v0",
|
| 283 |
+
"d35f5efca2a60d63c4b6-v1",
|
| 284 |
+
"d35f5efca2a60d63c4b6-v2",
|
| 285 |
+
"d35f5efca2a60d63c4b6-v3",
|
| 286 |
+
"c7714db5f938b7d85acb-v0",
|
| 287 |
+
"c7714db5f938b7d85acb-v1",
|
| 288 |
+
"c7714db5f938b7d85acb-v2",
|
| 289 |
+
"c7714db5f938b7d85acb-v3",
|
| 290 |
+
"65e3fde922ac3d23531c-v0",
|
| 291 |
+
"65e3fde922ac3d23531c-v1",
|
| 292 |
+
"65e3fde922ac3d23531c-v2",
|
| 293 |
+
"65e3fde922ac3d23531c-v3",
|
| 294 |
+
"bc4619d7cd2a0a22a0db-v0",
|
| 295 |
+
"bc4619d7cd2a0a22a0db-v1",
|
| 296 |
+
"bc4619d7cd2a0a22a0db-v2",
|
| 297 |
+
"bc4619d7cd2a0a22a0db-v3",
|
| 298 |
+
"57931985b05b3df37cb3-v0",
|
| 299 |
+
"57931985b05b3df37cb3-v1",
|
| 300 |
+
"57931985b05b3df37cb3-v2",
|
| 301 |
+
"57931985b05b3df37cb3-v3",
|
| 302 |
+
"69323a0945566e60c044-v0",
|
| 303 |
+
"69323a0945566e60c044-v1",
|
| 304 |
+
"69323a0945566e60c044-v2",
|
| 305 |
+
"69323a0945566e60c044-v3",
|
| 306 |
+
"a167a77232c4ca4795d2-v0",
|
| 307 |
+
"a167a77232c4ca4795d2-v1",
|
| 308 |
+
"a167a77232c4ca4795d2-v2",
|
| 309 |
+
"a167a77232c4ca4795d2-v3",
|
| 310 |
+
"3eec7426834f92771ac7-v0",
|
| 311 |
+
"3eec7426834f92771ac7-v1",
|
| 312 |
+
"3eec7426834f92771ac7-v2",
|
| 313 |
+
"3eec7426834f92771ac7-v3",
|
| 314 |
+
"0872ba96c873ac55e532-v0",
|
| 315 |
+
"0872ba96c873ac55e532-v1",
|
| 316 |
+
"0872ba96c873ac55e532-v2",
|
| 317 |
+
"0872ba96c873ac55e532-v3",
|
| 318 |
+
"b9dcd7e6a510a0952c17-v0",
|
| 319 |
+
"b9dcd7e6a510a0952c17-v1",
|
| 320 |
+
"b9dcd7e6a510a0952c17-v2",
|
| 321 |
+
"b9dcd7e6a510a0952c17-v3",
|
| 322 |
+
"866805ebff659448f234-v0",
|
| 323 |
+
"866805ebff659448f234-v1",
|
| 324 |
+
"866805ebff659448f234-v2",
|
| 325 |
+
"866805ebff659448f234-v3",
|
| 326 |
+
"f750f07092510231c565-v0",
|
| 327 |
+
"f750f07092510231c565-v1",
|
| 328 |
+
"f750f07092510231c565-v2",
|
| 329 |
+
"f750f07092510231c565-v3",
|
| 330 |
+
"99bbae502355dd6cb0ec-v0",
|
| 331 |
+
"99bbae502355dd6cb0ec-v1",
|
| 332 |
+
"99bbae502355dd6cb0ec-v2",
|
| 333 |
+
"99bbae502355dd6cb0ec-v3"
|
| 334 |
+
],
|
| 335 |
+
"parameters": 306321,
|
| 336 |
+
"teachers": [
|
| 337 |
+
"mesh-proxy:allenai/objaverse",
|
| 338 |
+
"mesh-proxy:scenario-labs/3d-collection"
|
| 339 |
+
],
|
| 340 |
+
"validation": "held-out objects",
|
| 341 |
+
"manifest_sha256": "1c446a51de294439cfc2244dd0cee936485ee5b70bbcdef6795c7cb09e742904",
|
| 342 |
+
"initialization": {
|
| 343 |
+
"sha256": "dd1a1719541c5603125e7f9379b0ad8ede20b7e9f2816a04e9120244cdbf528e",
|
| 344 |
+
"config": {
|
| 345 |
+
"grid": 8,
|
| 346 |
+
"width": 64
|
| 347 |
+
},
|
| 348 |
+
"step": 100,
|
| 349 |
+
"optimizer": "fresh AdamW; weights-only post-training"
|
| 350 |
+
},
|
| 351 |
+
"steps_requested": 5000,
|
| 352 |
+
"learning_rate": 0.0001,
|
| 353 |
+
"batch_size": 2,
|
| 354 |
+
"validation_fraction": 0.2,
|
| 355 |
+
"baseline_validation": {
|
| 356 |
+
"occupancy": 0.5287473667412996,
|
| 357 |
+
"position": 0.11035483225714415,
|
| 358 |
+
"colour": 0.07344755931990221,
|
| 359 |
+
"scale": 0.6529320403933525,
|
| 360 |
+
"rotation": 0.007450982979207765,
|
| 361 |
+
"opacity": 0.0016474263943564438,
|
| 362 |
+
"geometry": 0.0,
|
| 363 |
+
"loss": 0.8536830507218838,
|
| 364 |
+
"occupancy_iou": 0.2525805914774537
|
| 365 |
+
}
|
| 366 |
+
}
|