isl-org / Open3D

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

Color ICP end up with zero interations #3165

Closed ninglixu closed 2 years ago

ninglixu commented 3 years ago

I use two pointcloud with about 30m difference only in z direction. And i run the code just like the tutorial colored icp code. But the transformation is still identity matrix. After i centered two pointcloud to the origin and run color icp again, it works. I am confused if it is becasue convergence criteria or something else?

Thanks, the output is below.

init transformation: [[1. 0. 0. 0.] [0. 1. 0. 0.] [0. 0. 1. 0.] [0. 0. 0. 1.]]

  1. Colored point cloud registration [50, 2, 0] 3-1. Downsample with a voxel size 2.00 [Open3D DEBUG] Pointcloud down sampled from 1253027 points to 73336 points. [Open3D DEBUG] Pointcloud down sampled from 7341918 points to 401334 points. 3-2. Estimate normal. 3-3. Applying colored point cloud registration [Open3D DEBUG] InitializePointCloudForColoredICP [Open3D DEBUG] ICP Iteration #0: Fitness 0.0000, RMSE 0.0000 RegistrationResult with fitness=0.000000e+00, inlier_rmse=0.000000e+00, and correspondence_set size of 0 Access transformation to get result. [30, 1, 1] 3-1. Downsample with a voxel size 1.00 [Open3D DEBUG] Pointcloud down sampled from 1253027 points to 273331 points. [Open3D DEBUG] Pointcloud down sampled from 7341918 points to 1548675 points. 3-2. Estimate normal. 3-3. Applying colored point cloud registration [Open3D DEBUG] InitializePointCloudForColoredICP [Open3D DEBUG] ICP Iteration #0: Fitness 0.0000, RMSE 0.0000 RegistrationResult with fitness=0.000000e+00, inlier_rmse=0.000000e+00, and correspondence_set size of 0 Access transformation to get result. [14, 0.5, 2] 3-1. Downsample with a voxel size 0.50 [Open3D DEBUG] Pointcloud down sampled from 1253027 points to 733914 points. [Open3D DEBUG] Pointcloud down sampled from 7341918 points to 4326760 points. 3-2. Estimate normal. 3-3. Applying colored point cloud registration [Open3D DEBUG] InitializePointCloudForColoredICP [Open3D DEBUG] ICP Iteration #0: Fitness 0.0000, RMSE 0.0000 RegistrationResult with fitness=0.000000e+00, inlier_rmse=0.000000e+00, and correspondence_set size of 0 Access transformation to get result. [Open3D DEBUG] Add geometry and update bounding box to [(310.9743, -3429.7363, 64.5185) - (902.7206, -2891.1860, 96.8260)] [Open3D DEBUG] Add geometry and update bounding box to [(255.4653, -3922.9966, 7.2478) - (1465.8397, -2744.0100, 96.8260)]
reyanshsolis commented 3 years ago

Hi @Ggs1mida, Thanks for reaching out. As I can see there are no correspondences between the point cloud, so the possible reason may be that the max_correspondence_distance parameter is smaller than the distance between the two point clouds.

One solution can be to increase the max_correspondence_distance parameter such that it is able to find correspondences between two point clouds, but it is NOT advisable, as it will increase the query time unreasonably. Therefore It is advisable to provide a good initial transformation matrix guess in ICP.

If you may share your code, I can try to help you better. Thanks and Regards, Rishabh Singh

ninglixu commented 3 years ago

Thanks for replying. @reyanshsolis . The code looks like this.

def color_icp(source,target):

colored pointcloud registration

# This is implementation of following paper
# J. Park, Q.-Y. Zhou, V. Koltun,
# Colored Point Cloud Registration Revisited, ICCV 2017
voxel_radius = [2, 1, 0.5]
max_iter = [1000, 1000, 1000]
current_transformation = np.identity(4)
target_center=target.get_center()
source_center=source.get_center()
shift=source_center-target_center
current_transformation[0:3,3]=-shift
print("init transformation:")
print(current_transformation)
print("3. Colored point cloud registration")
for scale in range(3):
    iter = max_iter[scale]
    radius = voxel_radius[scale]
    print([iter, radius, scale])

    print("3-1. Downsample with a voxel size %.2f" % radius)
    source_down = source.voxel_down_sample(radius)
    target_down = target.voxel_down_sample(radius)

    print("3-2. Estimate normal.")
    source_down.estimate_normals(
        o3d.geometry.KDTreeSearchParamHybrid(radius=radius * 2, max_nn=30))
    target_down.estimate_normals(
        o3d.geometry.KDTreeSearchParamHybrid(radius=radius * 2, max_nn=30))

    print("3-3. Applying colored point cloud registration")
    loss = o3d.pipelines.registration.TukeyLoss(k=0.5)
    result_icp = o3d.pipelines.registration.registration_colored_icp(
        source_down, target_down, radius, current_transformation,
        o3d.pipelines.registration.TransformationEstimationForColoredICP(lambda_geometric=0.3,kernel=loss),
        o3d.pipelines.registration.ICPConvergenceCriteria(relative_fitness=1e-6,
                                                        relative_rmse=1e-6,
                                                        max_iteration=iter))
    current_transformation = result_icp.transformation
    print(result_icp)
return result_icp
theNded commented 2 years ago

Apparently the two point clouds are too far away (30m), and no correspondence will be found within the search radius (2m), so the algorithm quits without running. The centering practice was a good solution.