DFRANSACGlobalRegistration component

Contents

_images/icon25.png

DFRANSACGlobalRegistration component#

Register two point clouds together with a feature matching based on RANSAC.

Inputs:

i_cloud_source (pointcloud ,item)

The source point cloud.

i_cloud_target (pointcloud ,item)

The target cloud.

i_radius_kd_search (float ,item)

The radius used to search for neighbors in the KDTree.it is expressed relative to the point cloud size (0.01 means radiusKDTreeSearch = 1% of maxSize(pointCloud). It is used for the calculation of FPFHFeatures.

i_neighbours_kd_search (int ,item)

The maximum number of neighbors to search for in the KDTree. It is used for the calculation of FPFHFeatures. A higher value will result in heavier computation but potentially more precise.

i_max_corrspondence_dist (float ,item)

The maximum distance between correspondences. A higher value will result in more correspondences, but potentially include wrong ones.

is_t_estimate_pt2pt (bool ,item)

If true it deforms the cloud to match. The transformation estimation method to use. By default, it uses a point to point transformation estimation. If true it will scale and deform the cloud.

i_ransac_n (int ,item)

The number of points to sample in the source point cloud. A higher value can result in a more precise transformation, but will take more time to compute.

i_checker_dist (float ,item)

The maximum distance between correspondances in the FPFH space before testing a RanSaC model. It is exprimed in relative values (it is scaled by the size of the bounding box of the poinnt cloud).

i_similarity_threshold (float ,item)

The threshold for the ransac check based on edge length to consider a model as inlier. A higher value will be stricter, discarding more ransac models.

i_max_iterations (int ,item)

The maximum number of iterations to run the Ransac algorithm. A higher value will take more time to compute but increases the chances of finding a good transformation.

i_confidence_threshold (float ,item)

The threshold for the convergence criteria of the ransac models. A higher value will be stricter, discarding more ransac models.

Outputs:

o_x_form

The computed transformation.

Code:

#! python3


import Rhino
from ghpythonlib.componentbase import executingcomponent as component

from Grasshopper.Kernel import GH_RuntimeMessageLevel as RML

from diffCheck import diffcheck_bindings
from diffCheck import df_cvt_bindings


class DFRANSACGlobalRegistration(component):
    def RunScript(self,
        i_cloud_source: Rhino.Geometry.PointCloud,
        i_cloud_target: Rhino.Geometry.PointCloud,
        i_radius_kd_search: float,
        i_neighbours_kd_search: int,
        i_max_corrspondence_dist: float,
        is_t_estimate_pt2pt: bool,
        i_ransac_n: int,
        i_checker_dist: float,
        i_similarity_threshold: float,
        i_max_iterations: int,
        i_confidence_threshold: float
    ) -> Rhino.Geometry.Transform:
        if i_cloud_source is None or i_cloud_target is None:
            ghenv.Component.AddRuntimeMessage(RML.Warning, "Please provide both objects of type point clouds to align")  # noqa: F821
            return None
        if not i_cloud_source.ContainsNormals or not i_cloud_target.ContainsNormals:
            ghenv.Component.AddRuntimeMessage(RML.Error, "Please compute cloud's normals with a component before")  # noqa: F821

        # set default values
        if i_radius_kd_search is None:
            i_radius_kd_search = 1
        if i_neighbours_kd_search is None:
            i_neighbours_kd_search = 50
        if i_max_corrspondence_dist is None:
            i_max_corrspondence_dist = 0.5
        if is_t_estimate_pt2pt is None:
            is_t_estimate_pt2pt = False
        if i_ransac_n is None:
            i_ransac_n = 3
        if i_checker_dist is None:
            i_checker_dist = 0.5
        if i_similarity_threshold is None:
            i_similarity_threshold = 1.5
        if i_max_iterations is None:
            i_max_iterations = 5000
        if i_confidence_threshold is None:
            i_confidence_threshold = 0.999

        # conversion
        df_cloud_source = df_cvt_bindings.cvt_rhcloud_2_dfcloud(i_cloud_source)
        df_cloud_target = df_cvt_bindings.cvt_rhcloud_2_dfcloud(i_cloud_target)

        # fast registration
        df_xform = diffcheck_bindings.dfb_registrations.DFGlobalRegistrations.O3DRansacOnFeatureMatching(
            source=df_cloud_source,
            target=df_cloud_target,
            voxelize=False,  # set as default
            voxel_size=0.1,  # set as default
            radius_kd_tree_search=i_radius_kd_search,
            max_neighbor_kd_tree_search=i_neighbours_kd_search,
            max_correspondence_distance=i_max_corrspondence_dist,
            is_t_estimate_pt2pt=is_t_estimate_pt2pt,
            ransac_n=i_ransac_n,
            correspondence_checker_distance=i_checker_dist,
            similarity_threshold=i_similarity_threshold,
            ransac_max_iteration=i_max_iterations,
            ransac_confidence_threshold=i_confidence_threshold
        )
        print("-------------------")
        print("Estimated transformation matrix:")
        print(df_xform.transformation_matrix)
        print("-------------------")

        # cvt df xform to rhino xform
        df_xform_matrix = df_xform.transformation_matrix
        rh_form = Rhino.Geometry.Transform()
        for i in range(4):
            for j in range(4):
                rh_form[i, j] = df_xform_matrix[i, j]
        if rh_form == Rhino.Geometry.Transform.Identity:
            ghenv.Component.AddRuntimeMessage(RML.Warning, "The transformation matrix is identity, no transformation is applied")  # noqa: F821
            return None

        o_x_form = rh_form

        return o_x_form