isl-org / Open3D

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

Segmentation Fault for extract_voxel_grid #6712

Open hooyahliu opened 8 months ago

hooyahliu commented 8 months ago

Checklist

Describe the issue

When using Open3D 0.18.0 to execute self._volume.extract_voxel_grid() on the generated TSDF volume, the program exits with the error Segmentation fault (core dumped). But using 0.12.0 no error occurs.

Steps to reproduce the bug

class TSDFVolume(object):
    def __init__(self, size, resolution):
        self.size = size
        self.resolution = resolution
        self.voxel_size = self.size / self.resolution
        self.sdf_trunc = 4 * self.voxel_size

        self._volume = o3d.pipelines.integration.UniformTSDFVolume(
            length=self.size,
            resolution=self.resolution,
            sdf_trunc=self.sdf_trunc,
            color_type=o3d.pipelines.integration.TSDFVolumeColorType.NoColor,
        )

    def integrate(self, depth_img, intrinsic, extrinsic):
        """
        Args:
            depth_img: The depth image.
            intrinsic: The intrinsic parameters of a pinhole camera model.
            extrinsics: The transform from the TSDF to camera coordinates, T_eye_task.
        """
        rgbd = o3d.geometry.RGBDImage.create_from_color_and_depth(
            o3d.geometry.Image(np.empty_like(depth_img)),
            o3d.geometry.Image(depth_img),
            depth_scale=1.0,
            depth_trunc=2.0,
            convert_rgb_to_intensity=False,
        )

        intrinsic = o3d.camera.PinholeCameraIntrinsic(
            width=intrinsic.width,
            height=intrinsic.height,
            fx=intrinsic.fx,
            fy=intrinsic.fy,
            cx=intrinsic.cx,
            cy=intrinsic.cy,
        )

        extrinsic = extrinsic.as_matrix()
        self._volume.integrate(rgbd, intrinsic, extrinsic)

    def get_grid(self):
        shape = (1, self.resolution, self.resolution, self.resolution)
        tsdf_grid = np.zeros(shape, dtype=np.float32)
        voxels = self._volume.extract_voxel_grid().get_voxels()
        for voxel in voxels:
            i, j, k = voxel.grid_index
            tsdf_grid[0, i, j, k] = voxel.color[0]
        return tsdf_grid

Error message

Segmentation fault (core dumped)

Expected behavior

Return voxels.

Open3D, Python and System information

- Operating system: Ubuntu 20.04 
- Python version: Python 3.8 
- Open3D version: 0.18.0 0.12.0
- System architecture: x86
- Is this a remote workstation?: no
- How did you install Open3D?: pip

Additional information

No response

nicolaloi commented 6 months ago

When running the tutorial /examples/python/pipelines/rgbd_integration_uniform.py I get a segmentation fault or the program hangs indefinitely at voxel_grid = volume.extract_voxel_grid().

The probable cause is that VoxelGrid is a std::unordered_map, which is not thread-safe, so OpenMP hangs forever or throws a segfault. Problematic line: voxel_grid->voxels_[index] = geometry::Voxel(index, color); in cpp/open3d/pipelines/integration/UniformTSDFVolume.cpp.

An easy fix would be to remove the OpenMP parallelization (fix 1.). Other possible fixes are (fix 2.) use tbb:concurrent_unordered_map which is thread-safe, but then you have to convert it back to a std::unordered_map (which I presume is O(n)?), or (fix 3.) use multiple std::unordered_maps, one for each thread, and then merge them after the parallelization (which would be O(n) average case). I have tested fix 1. and fix 2. for multiple voxel resolutions (16, 32, 64, 128, 256, 512, 768), and their timings are practically the same. @ssheorey do you have any other ideas?