isl-org / Open3D

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

segmentation fault when using `open3d.geometry.PointCloud.hidden_point_removal` #2965

Open Tofull opened 3 years ago

Tofull commented 3 years ago

Describe the bug I use open3d and hidden_point_removal for months without any issue. Recently, I got one case which causes me troubles.

A segmentation fault occurs when using hidden_point_removal function and I didn't succeed to catch why. This happened only once, but it is still reproductible.

To Reproduce Steps to reproduce the behavior:

Here are the txt files containing datasets:

and a small script to reproduce the issue. It will load the data from both txt files, check convex hull, and then use hidden_point_removal function for each dataset.

import numpy as np
import open3d as o3d

def load_bad_data():
    xyz = np.loadtxt("test_bad.txt", delimiter=",")

    assert xyz.shape == (157862, 3)

    min_bound = np.min(xyz, axis=0)
    max_bound = np.max(xyz, axis=0)
    assert np.allclose(min_bound, np.array([-48.94669787, -40.96437845, -3.41310365]))
    assert np.allclose(max_bound, np.array([50.92755409, 59.71741356, 17.19930483]))

    bound_diff = max_bound - min_bound
    assert np.allclose(bound_diff, np.array([99.87425196, 100.68179201, 20.61240848]))

    return xyz

def load_good_data():
    xyz = np.loadtxt("test_good.txt", delimiter=",")

    assert xyz.shape == (1172, 3)

    min_bound = np.min(xyz, axis=0)
    max_bound = np.max(xyz, axis=0)
    assert np.allclose(min_bound, np.array([-58.16689297, -50.24060715, -4.05097986]))
    assert np.allclose(max_bound, np.array([49.4774204, 51.00874277, 5.42619586]))

    bound_diff = max_bound - min_bound
    assert np.allclose(bound_diff, np.array([107.64431336, 101.24934993, 9.47717572]))

    return xyz

def find_visible_points(xyz):
    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(xyz)

    diameter = np.linalg.norm(
        np.asarray(pcd.get_max_bound()) - np.asarray(pcd.get_min_bound())
    )
    radius = diameter * 50

    # 🔽 something wrong happens here
    _, visible_index = pcd.hidden_point_removal([0, 0, 0], radius)

    return visible_index

def display_pointcloud(xyz):
    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(xyz)

    hull, _ = pcd.compute_convex_hull()
    hull_ls = o3d.geometry.LineSet.create_from_triangle_mesh(hull)
    hull_ls.paint_uniform_color((1, 0, 0))
    o3d.visualization.draw_geometries([pcd, hull_ls])

if __name__ == "__main__":
    # happy test
    xyz_good = load_good_data()
    display_pointcloud(xyz_good)
    find_visible_points(xyz_good)

    # when the bug occurs
    xyz_bad = load_bad_data()
    display_pointcloud(xyz_bad)  # this shows that the bug is not related to the convex hull computation
    find_visible_points(xyz_bad)  # this will generate a segmentation fault

    print("Yeah!")  # this is never executed due to the segmentation fault

This will work as expected until the find_visible_points(xyz_bad) statement generates a segmentation fault:

$ python  -X faulthandler test_open3d.py 
Windows fatal exception: access violation

Current thread 0x00005eb0 (most recent call first):
  File "test_open3d.py", line 46 in find_visible_points
  File "test_open3d.py", line 68 in <module>
Segmentation fault

Expected behavior No segmentation fault, or at least raise an Exception python can catch.

Environment:

Additional context

I would be good to deal with this segmentation fault if Python allowed me to catch / handle the signal, but this completely shut off my script.

Hints:

chenjx1005 commented 2 years ago

@Tofull Do you find the solution of the problem?