Optimising parameters to allow ICP registration

Hi All

I am trying to select the best parameters for ICP registration dynamically.

This means I am trying to identify an objective function to select the best threshold value.

I have been using this:

def objective(thresh,source, target, trans_init):
evaluation = o3d.registration.evaluate_registration(source, target,thresh, trans_init)
return (1.0/(np.asarray(evaluation.correspondence_set).shape[0] * evaluation.fitness))

Basically my assumption was that the greater the number of inliers, the better the fit.

Needless to say it does not work.

What would you suggest as a better objective funciton to use to optimise via scipy.minimize?
I also wonder if I need to also optimise the parameters used to generate the normals, e.g.:

source.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.5, max_nn=300))

ie – do I also need to optimise the radius?

I then use this threshold value in the ICP registration…

reg_p2p = o3d.registration.registration_icp(
    source, target, threshold, trans_init,

Thanks for your help.

For question one, I think there might be a misunderstanding of the RANSAC algorithm. RANSAC’s target is to retrieve the best possible estimation from very noisy correspondences whose inlier ratio is usually low (< 50% I would say). If you use the objective function you defined, then in the extreme case, the threshold will be inf – in that case, the inlier ratio will be 1, but alas, that’s not we want. So basically, we can’t have control of inlier ratio because it is the intrinsic property of the data. We can only statistically verify the correct cases through many attempts. That means, scipy.minimize would not work either.

Based on that, in fact, there is no very good way to tune the thresholds as far as I know. We usually use empirical thresholds in our processing.
In Open3D, we usually use voxel_down_sample to control the voxel resolution of a point cloud, then use 3x/5x voxel size as a threshold that proved to work. The voxel size is another empirical choice – for indoor scene, usually 1cm-5cm works fine; for outdoor scene, it really depends on the scale.

Overall, it is a good catch that threshold has a big impact on these algorithms. The take away is that unfortunately today researchers still rely on empirical settings.

Hope this give you intuition.

Thanks for your comments – I’ll certainly have a further look at larger threshold values based on your 3x and 5x the voxel size. I’m running a 1 mm voxel size (from memory, id need to check).

I’ve certainly had little success attempting to optimise.

A more successful approach (if there is anyone else reading who is interested) has been to identify the precision of the scanning apparatus’s coordinates and camera pose, then run a sanity check on every transformation returned by the ICP algorithm. If translations and rotations exceed realistic parameters, the source cloud is rejected from the run, and then interactively I try to fix these rejected clouds subsequently, by adjusting the initial guess transformation. Sometimes fitting these troublesome
clouds into a much larger target enables a better automated fit anyway.

If you have multiple point clouds (>= 5 for instance) to be aligned altogether, I will recommend taking a look at Multiway Registration.

In multiway registration there is a robust loss function that takes the ‘sanity check’ into consideration: a weight is assigned to each correspondence; it will decrease during joint optimization when the pairwise registration is not reasonable, and the correspondence will be pruned if the weight is lower than a threshold.

I think the 3d point-to-point evaluation is rather a relative than a global indicator of the good registration unless the two point clouds are geometrical complex and significant overlap.

If the point cloud is from rgbd, then you could transform them back to 2d images to check them at the pixel level.