isl-org / Open3D

Open3D: A Modern Library for 3D Data Processing
http://www.open3d.org
Other
11.47k stars 2.31k forks source link

Point-To-Plane registration error #3066

Closed GabrieleGalimberti-GaleSelector closed 3 years ago

GabrieleGalimberti-GaleSelector commented 3 years ago

Hi,

I want to make a Point-To-Plane Registration with this code:

def registrazione_point_to_plane(source_pcd, target_pcd, max_correspondence_distance_fine):
    source=copy.deepcopy(source_pcd)
    target=copy.deepcopy(target_pcd)
    icp_fine = o3d.pipelines.registration.registration_icp(
        source,
        target,
        max_correspondence_distance_fine,
        np.identity(4),
        o3d.pipelines.registration.TransformationEstimationPointToPoint(),
        o3d.pipelines.registration.ICPConvergenceCriteria(max_iteration=1000))

    icp_fine = o3d.pipelines.registration.registration_icp(
        source, target, max_correspondence_distance_fine, icp_fine,
        o3d.pipelines.registration.TransformationEstimationPointToPlane())

    transformation_icp = icp_fine.transformation
    information_icp = o3d.pipelines.registration.get_information_matrix_from_point_clouds(source,target,max_correspondence_distance_fine,icp_fine.transformation)
    return transformation_icp, information_icp

transformations = []
transformations.append(np.identity(4))
information_icp1 = []
n_pcds = len(pcds)
max_correspondence_distance_fine = 0.1

for source_id in range(n_pcds-1):
    source = copy.deepcopy(pcds[source_id])
    target = copy.deepcopy(pcds[source_id+1])
    source.translate(gps_xyz[point_id])
    target.translate(gps_xyz[point_id+1])

    source = source.uniform_down_sample(every_k_points=20)
    target = target.uniform_down_sample(every_k_points=20)

    radius_normal = voxel_size * 2
    # print(":: Estimate normal with search radius %.3f." % radius_normal)
    source.estimate_normals(
        o3d.geometry.KDTreeSearchParamHybrid(radius=radius_normal, max_nn=10))
    target.estimate_normals(
        o3d.geometry.KDTreeSearchParamHybrid(radius=radius_normal, max_nn=10))

    t, information_icp = registrazione_point_to_plane( source , target , max_correspondence_distance_fine)
    transformations.append(t)
    information_icp1.append(information_icp)
    print(source_id)

but I find this error:


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-45-c1bd797d1153> in <module>
     40         o3d.geometry.KDTreeSearchParamHybrid(radius=radius_normal, max_nn=10))
     41 
---> 42     t, information_icp = registrazione_point_to_plane( source , target , max_correspondence_distance_fine)
     43     transformations.append(t)
     44     information_icp1.append(information_icp)

<ipython-input-45-c1bd797d1153> in registrazione_point_to_plane(source_pcd, target_pcd, max_correspondence_distance_fine)
     12     icp_fine = o3d.pipelines.registration.registration_icp(
     13         source, target, max_correspondence_distance_fine, icp_fine,
---> 14         o3d.pipelines.registration.TransformationEstimationPointToPlane())
     15 
     16     transformation_icp = icp_fine.transformation

TypeError: registration_icp(): incompatible function arguments. The following argument types are supported:
    1. (source: open3d.cpu.pybind.geometry.PointCloud, target: open3d.cpu.pybind.geometry.PointCloud, max_correspondence_distance: float, init: numpy.ndarray[float64[4, 4]] = array([[1., 0., 0., 0.],
       [0., 1., 0., 0.],
       [0., 0., 1., 0.],
       [0., 0., 0., 1.]]), estimation_method: open3d.cpu.pybind.pipelines.registration.TransformationEstimation = TransformationEstimationPointToPoint without scaling., criteria: open3d.cpu.pybind.pipelines.registration.ICPConvergenceCriteria = ICPConvergenceCriteria class with relative_fitness=1.000000e-06, relative_rmse=1.000000e-06, and max_iteration=30) -> open3d.cpu.pybind.pipelines.registration.RegistrationResult

Invoked with: PointCloud with 1468 points., PointCloud with 1466 points., 0.1, RegistrationResult with fitness=4.441417e-01, inlier_rmse=4.252150e-02, and correspondence_set size of 652
Access transformation to get result., TransformationEstimationPointToPlane```

Can you help me please?
cbenitez81 commented 3 years ago

I think that icp_fine is an object with inliers rms among others, and you want to pass just the icp_fine.transformation in that line. Also make sure that you have normals

reyanshsolis commented 3 years ago

Hi @cbenitez81, The function arguments are incorrect for o3d.pipelines.registration.registration_icp

    reg_p2p = o3d.pipelines.registration.registration_icp(
        source, target, threshold, trans_init,
        o3d.pipelines.registration.TransformationEstimationPointToPoint(),
        o3d.pipelines.registration.ICPConvergenceCriteria(max_iteration=2000))

Here reg_p2p and trans_init have different types. reg_p2p is a class having reg_p2p.transformation, reg_p2p.fitness, reg_p2p.rmse, whereas trans_init is a {4,4} matrix. [reg_p2p.transformation and trans_init are same type and shape (both are transformation matrix)].

So, I am not sure why you are using

   icp_fine = o3d.pipelines.registration.registration_icp(
        source, target, max_correspondence_distance_fine, icp_fine,
        o3d.pipelines.registration.TransformationEstimationPointToPlane())

Just removing it will solve your issue.

Thanks.

GabrieleGalimberti-GaleSelector commented 3 years ago

Thank you, I wasn't careful enough