Add DiG (DINO-embedded Gaussians) feature training#511
Open
connorsoohoo wants to merge 1 commit into
Open
Conversation
Port of the DiG model from Robot See Robot Do (reference: kerrj/dig, MIT) running on all Brush backends: per-Gaussian DINO feature embeddings trained alongside RGB via a dedicated feature rasterizer, with .npy feature-map loading, per-splat feature table + MLP decoder training, feature export next to the PLY, a live viewer feature-view toggle, and a self-contained DINOv2 extraction script. Explicit opt-in via --dino; no new Rust deps. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Implements the DiG model from Robot See Robot Do (reference implementation: kerrj/dig, MIT) natively in Brush: per-Gaussian DINO feature embeddings trained alongside RGB, useful for downstream part segmentation and tracking. The reference stack is CUDA-only (nerfstudio/gsplat/tiny-cuda-nn); this port runs on every Brush backend, including Metal and the web.
Everything is explicit opt-in via
--dino— with the flag off there is no change to training, and the feature pass adds no cost. No new Rust dependencies.What's in it
brush-render/brush-render-bwd): a new forward kernel reusing the existing projection/sort pipeline; the 64-d per-Gaussian feature vector is read from global memory only for contributing splats, so the feature dimension isn't bound by the 32 KiB threadgroup budget. The backward is a forward-order replay scattering gradients via the existingAtomicAddF32(CAS fallback on Metal). Geometry is detached in the feature pass — matching the reference — so this is a single-input autodiff custom op with no changes to the RGB backward.brush-dataset): per-view.npyfeature-map loading (--features-dir-name, defaultdino_features), with a minimal pure-Rust npy reader.brush-train): per-Gaussian[N, 64]feature table + shared no-bias MLP decoder (64→64→64→96), DINO MSE at 5× the GT feature resolution with bilinear-upsampled GT, 3-NN feature-variance regularizer after step 1000 (CPU grid-hash kNN, recomputed on refine), the reference LR schedule (1e-2→1e-3 over 6k steps), and prune/split remapping of the feature table + its Adam state in refine. All reference constants are CLI flags with the reference values as defaults (--dino-feature-dim,--dino-rescale-factor,--dino-lr/--dino-lr-end,--dino-nn-reg-weight).brush-process):<name>_dig_features.npy(rows match PLY order) +<name>_dig_mlp.jsonalongside every exported PLY, so features survive round-trips out of Brush.--dino-viewstarts with it enabled.scripts/extract_dino_features.py— DINOv2 → PCA cache, numerically matching the reference format; runs on MPS/CUDA/CPU; self-contained via PEP 723 (uv runneeds no env setup).docs/dig-port/dig-port-usage.md— end-to-end usage; a short README section.Tests
crates/brush-bench-test/tests/dig_features.rs:Full workspace test suite,
clippy --all-targets -D warnings,cargo fmt --check, and a wasm32cargo checkpass locally (macOS/Metal).Known limitations
--lod-levels > 0) resets the trainer between levels and isn't supported with feature training (--dino+--lod-levelserrors out with a clear message).Happy to split this up or adjust conventions (flag names, doc placement) however you prefer.
🤖 Generated with Claude Code