Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CPD and make ICP Python-based #701

Draft
wants to merge 30 commits into
base: main
Choose a base branch
from

Conversation

rhugonnet
Copy link
Member

@rhugonnet rhugonnet commented Mar 11, 2025

Ongoing...

This PR adds Coherent Point Drift (CPD) coregistration, and modifies Iterative Closest Point (ICP) coregistration to be fully Python-based. This allows to remove the (heavy) OpenCV dependency, and call consistent optimizer/parameters compared to other methods.

As both methods are point registration, a new preprocessing shared by both methods has to be introduced, which is why they are in the same PR.

This PR takes over #581, which is closed. It is possible thanks to #530 to use the same core functions as other coregs.

Implementation details

ICP

This PR adds many options of ICP to ensure the best accuracy and performance, equal to that of OpenCV or Open3D's implementation (tested outside of xDEM, see details on this further below).

Those are:

  • The basic "point-to-point" implementation (cost function computed is simply the 3D distance) introduced in Besl and McKay (1992), https://doi.org/10.1117/12.57955/.
  • The "point-to-plane" implementation (cost function is 3D distance projected on the plane normals), described in Chen and Medioni (1992), https://doi.org/10.1016/0262-8856(92)90066-C, which performs better in some use cases, especially when the 3D point cloud represent a surface (like DEMs).
  • The minimization to estimate the transform at each iteration: As for all coregistration in xDEM, the minimization step can be passed any optimizer (like scipy.optimize.least_squares).
  • For small rotations (<30°) and the "point-to-plane" method, we include a linearized approximation to the ICP least-squares problem that allows to speed-up the computation of the rigid transformation at each iteration, based on Low (2004), https://www.comp.nus.edu.sg/~lowkl/publications/lowk_point-to-plane_icp_techrep.pdf,
  • For outlier-prone data, or data sets that simply have different extent, the selection of closest neighbours is sometimes redundant and reduce performance. We add two "Picky ICP" options described in Zinsser et al. (2003), http://www5.informatik.uni-erlangen.de/Forschung/Publikationen/2003/Zinsser03-ARI.pdf, to remedy this. The first option removes target points that are matched with a same reference point, keeping only the pair with the minimum distance. The second option performs an outlier rejection based on the distances between all pairs.
  • For speed-up of all methods, we add a multi-resolution scheme which loops over all iteration, each time with a different subset of the full subsample, based on Jost and Hugli (2002), https://ieeexplore.ieee.org/document/1024114.

CPD

This PR adds a fully NumPy-based implementation of CPD relying on pycpd's rigid implementation: https://github.com/siavashk/pycpd/blob/master/pycpd/rigid_registration.py.

CPD has trouble for unscaled data, so we need to add scaling options to xDEM to properly use it.
This is ongoing, see to-do below...

Benchmarking our Python ICP, and more?

In order to benchmark that our ICP performs as well as other algorithms out there, both in terms of accuracy and speed, I've separately written a Python module that runs ICP from OpenCV, Open3D, and other packages. This is currently on a separate repository (as we don't want these dependencies in xDEM).
Should we add that new module into a xdem-benchmark or similar, that can punctually install/run other packages and xDEM, to compare the performance of all these algorithms?

We could consider adding other algorithms to this repo, for instance the ICP of py4dgeo (#504), or of libpointmatcher (potentially via ASP too): #11.
But also other algorithms, in time, if we want (check CPD implementation, etc).

TO-DO to finalize

  • Add weight support to ICP,
  • Finalize Picky ICP options,
  • Add multi-resolution options,
  • Ensure preprocessing sampling never returns NaNs...
  • Add "scaling" options to all methods to improve algorithm convergence: "uniform" (all axes scaled by the same value), "hv" (horizontal and vertical scaled by a different value), "xyz" (each axis scaled by a different value). Only "uniform" is allowed when a rotation is activated, otherwise the transformation is not reversible.
  • Add "only_translation" option to both ICP and CPD (to allow the use of "hv" and "xyz" scaling).

Resolves #100
Resolves #483

@rhugonnet rhugonnet mentioned this pull request Mar 11, 2025
@rhugonnet rhugonnet marked this pull request as draft March 11, 2025 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Python-based ICP to support weights Add rigid CPD coregistration
1 participant