Skip to content

Releases: Archerkattri/splatreg

v1.3.2 — Phase 4: verified examples + Sim(3) autodiff fix

11 Jun 13:45

Choose a tag to compare

What's new

Bug fixes

  • Sim(3) autodiff Jacobian graph accumulation (solvers/lm.py): detach T before passing it into the jacrev closure. Without this, autograd accumulated a growing computation graph across LM iterations, causing quadratic memory use and eventual OOM on large inputs.

Tests

  • tests/test_solver.py: new regression test test_sim3_autodiff_jacobian_detaches_T gates the fix against future regressions.

Examples

  • examples/merge_demo.py restructured: the synthetic mode now uses a full-object A and B = Sim(3)(A) instead of mismatched partial crops. This matches the realistic "two complete reconstructions in different frames" scenario and produces meaningful metrics (rot 0.6°, 68.7x Chamfer improvement, overlap 0.199 → 1.000).

Validation

  • pytest: 152/152 passed
  • examples/validate_recovery.py on GPU: 36/36 cells, 100% success rate, 172s, 0.15 GiB peak

v1.3.1 — SDF residual weight fix (load-bearing)

10 Jun 20:49

Choose a tag to compare

Bug-fix release from an independent whole-repo review.

Fixed

  • The Gaussian-SDF residual pre-multiplied its weight in both residual() and jacobian() while the solver also applies sqrt(weight): the objective scaled as weight cubed, so the default register stack ran SDF at an effective 0.027 instead of the documented 0.3. The solver now owns the weight, applied exactly once, matching every other residual. Regression test asserts linear weight scaling in the assembled normal equations.
  • merge() and bundle fusion now normalize mixed log/linear scale conventions before concatenation (mixing a PLY-loaded splat with a from_gsplat splat no longer corrupts fused scales).
  • knn() on an empty spatial index returns empty instead of crashing, matching radius().

Honesty note: the official 3DMatch (91.5 percent) and 3DLoMatch (72.5 percent) results are unaffected (the learned pipeline does not use the SDF residual). The synthetic-recovery and splat-tool numbers in RESULTS section 5c were measured under the old weighting; they remain within all validation gates after the fix and will be re-measured in the next benchmark pass.

pip install -U splatreg

splatreg 1.3.0: MAC seed, the honest verdict, and the production sweep

10 Jun 12:35

Choose a tag to compare

splatreg 1.3.0

The production-sweep release: the MAC maximal-clique seed with its honest measured verdict, the align-without-merge workflow, and a full code/docs audit. Every claim below traces to a recorded run or a test (RESULTS.md).

init="mac": maximal-clique correspondence seed (Zhang et al., CVPR 2023)

Pure torch + networkx reimplementation (pip install "splatreg[mac]"): SC2-weighted rigidity compatibility graph, Bron-Kerbosch maximal cliques as consensus hypotheses, weighted SVD per clique, plus a Sim(3) extension via the median pairwise-distance-ratio scale. Measured (tests/test_mac.py):

  • matches the fast-init RANSAC engine at 30/60/90% random outliers (rot err <= 0.2 deg);
  • decisively wins the structured-decoy regime: on a 90%-contaminated set with a reflection-consistent decoy cluster the greedy-prefilter+RANSAC engine fails at ~78 deg while MAC stays < 0.2 deg;
  • all-outlier sets return an honest success=False identity, never a silent wrong pose;
  • 500 correspondences run in ~0.1 s on a 2-thread CPU.

The official-split verdict, stated honestly

seed_selector="mac" runs MAC over GeoTransformer's learned correspondences on the full official 3DMatch/3DLoMatch splits (same forward, same native 0.025 voxel, same residual-gated refine; only the hypothesis stage differs). Result: a wash, not a lift. 3DLoMatch 72.1% mean / 74.6% pooled (MAC) vs 72.5% / 74.4% (LGR); 3DMatch 91.7% / 93.8% vs 91.5% / 93.5%; every delta within plus or minus 4 pairs, at ~+50% runtime. At native voxel the learned correspondences are already consensus-dominated (median 600-800 MAC inliers), so seed_selector="lgr" stays the default and "mac" remains the tool for genuinely contaminated correspondence sets (RESULTS.md section 5k).

Carried forward from 1.2.0 (same-day release)

  • SH Wigner rotation: higher-order SH bands (f_rest) now rotate with the splat in apply_transform / merge / the align CLI (Ivanic-Ruedenberg real-basis Wigner-D, 3DGS sign convention); rotated-coefficient evaluation matches an independent basis evaluator to ~2.4e-15 in float64.
  • Public apply_transform() and the single-forward align-without-merge workflow: register two scans, bake the recovered SE(3)/Sim(3) into the source, keep both scans as separate registered PLYs.
  • Photometric exposure compensation (default ON) and the coarse-to-fine render ladder: a x1.3 tint that absorbed into the Sim(3) scale (0.10% -> 3.99% scale error) recovers to 0.47% with compensation; the 32-64-96 ladder lands 2.55 deg where a cold single rung stalls at 5.61 deg.
  • Pose covariance: builtin-LM solves expose info["information"] / info["covariance"] for pose-graph weighting (None when singular, never faked).

Production sweep

  • Dead code removed, ruff clean across package/tests/benchmarks; CLI and the Colab notebook now use the public apply_transform.
  • README restructured as a storefront: capability matrix vs the alternative splat tools, results table with per-row provenance.
  • Docs refreshed: https://archerkattri.github.io/splatreg/ (MAC verdict, SH rotation, covariance, align-without-merge).
  • CHANGELOG.md added.

Gate

143 tests passing (CPU, CUDA_VISIBLE_DEVICES=""), validate_recovery.py --fast 6/6 cells within gate, mkdocs build --strict clean.

Install: pip install splatreg==1.3.0 · Docs: https://archerkattri.github.io/splatreg/ · Cite: DOI 10.5281/zenodo.20618389

v1.2.0 — SH Wigner rotation · exposure compensation · render ladder · pose covariance

10 Jun 03:49

Choose a tag to compare

splatreg 1.2.0 — the correctness release.

Spherical harmonics now rotate correctly. Real-basis Wigner-D rotation (any degree; Ivanic–Ruedenberg recurrence with the 1998 erratum corrections, conjugated into the 3DGS f_rest sign convention) is baked into apply_transform, merge, and the align CLI. Verified renderer-free to 2.4e-15: evaluating rotated coefficients at d equals evaluating the originals at R⁻¹d, plus closed-form l=1, composition, and PLY round-trip tests. To our knowledge splatreg is the only splat registrar that rotates view-dependent color correctly. Also exported standalone: splatreg.rotate_sh / sh_rotation_matrix.

Photometric refine upgrades

  • Per-pair exposure compensation (closed-form gain/bias, clamped, alternated with the pose LM, default ON): a ×1.3 tint that silently corrupted the recovered Sim(3) scale (0.10% → 3.99% error) is absorbed back to 0.47%, harmless on clean pairs.
  • Coarse-to-fine render ladder (refine_kwargs["ladder"]): at equal budget, 5.61° (single rung) → 2.55°.

New API

  • RegisterResult.info["information"] / ["covariance"] — JᵀWJ and σ̂²(JᵀWJ)⁻¹ at convergence (6×6 SE(3) / 7×7 Sim(3)); None when singular, never faked. Unlocks pose-graph / submap fusion use.
  • apply_transform() — align scans without merging: bake the recovered transform into the source and save each scan as its own PLY (mirrors splatreg align).
  • validate_recovery.py --fast (6 cells, ~41 s CPU).

Test suite: 105 → 126 passed. Docs updated throughout.

pip install -U splatreg

v1.1.0 — CLI · photometric refinement · docs site

09 Jun 23:07

Choose a tag to compare

splatreg 1.1.0 — the CLI release, plus photometric refinement.

New

  • CLI: splatreg align a.ply b.ply -o aligned.ply / splatreg merge ... -o fused.ply / splatreg info x.ply — register and fuse standard 3DGS PLYs from the terminal (recorded run: 154 mm Chamfer → 0.05 mm).
  • Photometric refinement (register(..., refine="photometric")): a splat-to-splat photometric stage after the geometric solve — decisive where geometry under-constrains the pose (rotation-symmetric / texture-only cases: 5°/7 mm → 0.36°/0.5 mm with gsplat in ~1.1 s), neutral where geometry already converges. Opt-in; works with a custom render_fn without gsplat. Three-case benchmark in the docs.
  • Docs site: https://archerkattri.github.io/splatreg/ — quickstart, CLI guide, init modes, PLY interop (incl. the honest SH-rotation scoping), API reference, benchmarks.
  • Colab quickstart notebook (runs CPU-only end-to-end) + CITATION.cff.

Fixed

  • DC-only PLY colour round-trip: load_ply now returns RGB for DC-only files (2-D colors == RGB everywhere), fixing a load→save double-encode. Regression-locked.

105 tests, BSD-3-Clause. pip install -U splatreg

v1.0.2 — object-pose · camera-loc · bundle · spatial-index

08 Jun 08:52

Choose a tag to compare

splatreg 1.0.2 brings the full v0.2/v0.3 feature set to PyPI (was registration-only):

  • 6-DoF object-pose (estimate_object_pose) — ADD/ADD-S/AUC; YCB-CAD ADD-S AUC 0.995
  • Camera localization in a splat (localize_camera) — differentiable-render pose refine
  • Multi-splat bundle registration (bundle_register) — pose-graph + robust outlier rejection
  • Scene-scale spatial index (SpatialIndex) — voxel-hash knn/radius/region

69 tests, BSD-3-Clause. pip install -U splatreg

splatreg 1.0.1

07 Jun 16:38

Choose a tag to compare

Production release. Composable SE(3)/Sim(3) Gaussian-splat registration (inverse of gsplat) — matches GeoTransformer on official 3DMatch, real-splat merge, pluggable backends. pip install splatreg