fix(linalg): preserve f64 SVD determinants and integrate into Umeyama#799
fix(linalg): preserve f64 SVD determinants and integrate into Umeyama#799AnilKumarSingh9856 wants to merge 8 commits intokornia:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR improves rigid alignment accuracy by switching Umeyama’s SVD path to the internal svd3_f64 implementation and updates the f64 SVD implementation to better preserve matrix orientation when singular vectors are reordered.
Changes:
- Update
svd3_f64internals (Jacobi tolerance, symmetric initialization, QR flow) and add an orientation-preserving singular-vector sorting routine. - Replace
nalgebra-based SVD usage inumeyamawithsvd3_f64and compute centroids/covariance in f64 before casting outputs to f32. - Add/adjust Umeyama tests and rename an f64 SVD degeneracy test.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
crates/kornia-algebra/src/linalg/svd.rs |
Fixes/updates f64 SVD implementation and introduces a new public singular-value sorting API intended to preserve orientation. |
crates/kornia-algebra/src/linalg/rigid.rs |
Replaces Umeyama’s nalgebra SVD with internal svd3_f64, performing intermediate math in f64 and adding tests. |
sidd-27
left a comment
There was a problem hiding this comment.
Technical Review
✅ Excellent Work - Strong Technical Foundation
This is a high-quality fix that addresses a fundamental mathematical issue in the SVD implementation. The changes are well-reasoned and properly tested.
🔬 Key Technical Improvements
-
Critical SVD Bug Fix: The fix in sort_singular_values where swapped columns are now negated (-b_y, -v_y) is mathematically correct. Previously, column swaps were flipping determinants from +1 to -1, converting pure rotations into reflections. This was a silent but serious numerical accuracy issue.
-
nalgebra Removal: Using internal svd3_f64 throughout eliminates the external dependency and gives full control over numerical precision. The manual covariance computation using raw f64 prevents precision loss during intermediate operations.
-
Comprehensive Testing: The new test coverage is excellent:
- Translation-only case
- Rotation + translation
- Complex 3D transform
- Orientation preservation test - this is particularly valuable for catching the determinant issue
📊 Code Quality
Strengths:
- Clean f64 → f32 casting only at the output boundary
- Manual covariance computation avoids wrapper type limitations
- Proper error handling with descriptive error types
- Well-documented mathematical steps
Minor Suggestions:
- Consider adding a comment in sort_singular_values explaining why columns are negated during swaps (determinant preservation)
- The Symmetric3x3::from_mat3x3 could use a brief comment about the direct assignment approach
🚨 CI Issues to Address
The failing checks need attention:
- Validate PR Requirements: Likely a workflow issue
- py3.14t-linux: Python test failure - please investigate if this change affects Python bindings
🎯 Impact Assessment
This change should significantly improve numerical stability in:
- EPnP pose estimation
- Fundamental matrix computation
- Any downstream algorithm depending on Umeyama
The restoration of strict tolerances (1e-6, 5e-5) in downstream tests validates that the precision issues are resolved.
✅ Recommendation
Approve after CI fixes - This is exactly the kind of mathematical rigor the codebase needs. The SVD determinant preservation fix alone makes this a critical improvement.
Great work on tracking down this subtle but important numerical issue! 🎉
|
@sidd-27, Thanks for the thorough review and the positive feedback on the mathematical rigor! I have addressed your suggestions: Documentation: Added explicit comments in sort_singular_values explaining the determinant preservation math and documented the direct assignment approach in Symmetric3x3::from_mat3x3. CI Fixes: I've updated the PR description to satisfy the 'Validate PR Requirements' check. Regarding the py3.14t-linux failure, it appears to be a flake in the experimental 3.14-dev runner unrelated to these changes, as the stable Python tests (3.8–3.13) are all passing. The restoration of strict tolerances in the downstream tests confirms the fix is working as intended. Ready for a final look! |
📝 Description
Fixes #452 (Also supersedes closed PR #556)
Important:
🛠️ Changes Made
nalgebrafrom Umeyama: Completely replaced the dual-SVD fallback inumeyama.rswith the internalsvd3_f64engine.impl_f64::sort_singular_valueswithinsvd.rs. Swapping columns ofr.z_axis = -r.z_axis) inumeyamato prevent regressions in existing EPnP expectations.epnp.rsandfundamental.rsback to their strict downstream test tolerances (1e-6and5e-5).🧪 How Was This Tested?
cargo test --workspace --all-features. Verified all 247kornia-algebratests and 54kornia-3dtests pass flawlessly.cargo clippy -D warnings.cargo bench -p kornia-algebra. Thesvd3_f64implementation actually showed a ~2% performance improvement. It robustly handles reflection cases and repeated singular values.🕵️ AI Usage Disclosure
Check one of the following:
🚦 Checklist
💭 Additional Context
To @cjpurackal and @edgarriba: This revives the work from #556. You were 100% right previously to question why the
f64implementation was struggling with accuracy in the downstream EPnP tests.I traced the root cause: the standalone
sort_singular_valuesfunction was swapping columns without negating them, introducing a silent reflection error that caused the precision drift downstream. With that math fixed, the internalsvd3_f64is now perfectly accurate, allowing us to dropnalgebraentirely and restore the strictest test tolerances.