SlicerIGT Fiducial to Model registration details

Hi, I’m trying to figure out the ICP registration details used in SlicerIGT’s Fiducial to Model registration module.

I’m looking here: https://github.com/SlicerIGT/SlicerIGT/blob/master/FiducialsToModelRegistration/FiducialsToModelRegistration.py and https://github.com/Kitware/VTK/blob/master/Common/DataModel/vtkIterativeClosestPointTransform.cxx

Am I understanding correctly that only 200 points are used by default even if the surface model and markups node has many more points? How is the sampling achieved, is it uniform or based on distance?

Thanks

The beauty of VTK is that if you have any detailed question then you can go and read it in the code (and even modify as needed). VTK’s ICP implementation picks every N-th point for registration, see here:

Yes, I saw that part but unfortunately I got a little lost in the code (I’m not used to C++). Does it select every n-th point uniformly, or is it the N closest points per iteration?

The reason I am asking about this is that we are trying to replicate the SlicerIGT Fiducial-Model registration functionality in MATLAB. Although there is a built-in MATLAB ICP function, the optimization details are a little different and we are trying to match them exactly to what’s happening in Slicer and VTK. Currently, our post-registration mean distance error calculations are off by about 0.25mm

It uses every n-th point, so it is not a random or spatially uniform sampling, but it depends on the order of points in the point list (so, it is rather poor sampling and in unlucky cases, you can end up with spatially very non-uniform distribution).

The was always one of the major issues with Matlab: even though it had some high-quality algorithm libraries, their results were very often not reproducible (we could never reproduce exact same results as in Matlab in independent implementations). Since so many more packages are available for Python, many of them are very high quality, they are all open-source, reproducible, collaboratively developed, and widely accessible with non-restrictive licensing, nowadays it is really hard to find justification to use Matlab. Matlab still provides some unique tools for some niche applications, but it is not the best computing environment for engineers and scientists as it used to be 10-20 years ago.

In short, it may be hard to find people to help you with porting algorithms to Matlab from C++ or Python.

1 Like

Hi,
I am also working on this with Prash and thanks for your help so far. I looked through the code and am having trouble actually understanding the details of what it is doing. I see in lines 293 -298 that it is getting a step so it can step through the function and retrieve 200 points from the sample given at every step. Is this just done to the target points? Then it seems that only those points are transformed forward to make the error calculations? Is this process repeated every loop iteration or does it just need to be done once so only the nth points are run through the icp loop?

Only source points are sampled.

Only sampled points are used for error computation.

The same sampled source points are used in all iterations.

Thanks for the answers. Just to confirm, 200 points aren’t resampled every iteration of the icp? It looks like the 200 points are resampled every iteration as the step code starting on line 293 is within the icp loop starting on line 264? On 3d slicer in this Fiducial to Model registration the absolute mean distance error is given after the registration in the user interface not the RMS error. But it looks from the code that RMS is actually what is calculated and optimized by default? Can you clarify this? And final question, the loop will stop when the mean distance is <= max mean distance which is set to 0.01 by default? But when I have run the slicer module the mean distance errors I get are larger than 0.01 (maybe about 0.3mm to 1mm) so I am not sure how this is ever satisfied? Thank you!