利用Open3D从RGBD构建TSDF

输入:

  • RGB图像以及对应深度图
  • 相机内参与外参[图像轨迹]

输出:

  • TSDF表示的场景

    可进一步转换输出为:

    • Mesh
    • VoxelGrid
    • PointCloud

参考程序:

其中Open3D官方也提供了例程:https://github.com/isl-org/Open3D/blob/master/examples/python/pipelines/rgbd_integration.ipynb

本文不再重复例程中提供的代码,只记录一些值得关注的注意事项以及关键代码

  1. 网格创建

    # 创建ScalableTSDFVolume
    # ScalableTSDFVolume 能更好的适应大场景的TSDF
    # voxel_length:每个voxel的尺寸
    # sdf_trunc:截断距离
    # volume_unit_resolution:存储sdf的网格尺寸,越大内存越大,默认=16
    volume = o3d.pipelines.integration.ScalableTSDFVolume(voxel_length=6.0 / 512.0, sdf_trunc=0.02, color_type=o3d.pipelines.integration.TSDFVolumeColorType.RGB8, volume_unit_resolution = 256)
    
  2. 相机模型

    相机模型在volume.intergrate时需要作为变量传入,Open3D例程中使用默认的Pinhole相机[640*480],如果需要自定义自己的相机则需要自己按需创建。比如:

    # Pinhole : w,h,fx, fy, cx, cy
    cam = o3d.camera.PinholeCameraIntrinsic(1024, 576, 505.4856579685043, 505.4856579685043, 1024/2, 576/2)
    

    更多相机模型可参考Open3D doc:http://www.open3d.org/docs/release/python_api/open3d.camera.PinholeCameraIntrinsic.html。

    但似乎Open3D只支持Pinhole,如果遇到存在畸变的图像,不妨在最先处理前,就进行去畸变操作。

  3. 轨迹读取

    相机轨迹在volume.intergrate时需要作为变量传入,传入格式为4*4变换矩阵,坐标系定义为 from world to camera。如果轨迹中存储的是from camera to world(相机在世界坐标系),则需要inv。

    Open3D提供的例程提供了一种读取traj log的接口,这个方式并非唯一,只需要保证在每帧fusion的时候,能在变量中传入4*4变换矩阵即可。

  4. 深度读取

    例程中,需要先分别读取rgb图像和depth图像,然后在进一步生成rgbd图像,最后将rgbd图像传入intergrate步骤。

    值得注意的一点是,Open3D中默认的depth scale = 1000,因此如果不同格式存储的depth可能需要调整scale。

    # depth_scale (float, optional, default=1000.0) – The ratio to scale depth values. The depth values will first be scaled and then truncated.
    # depth_trunc (float, optional, default=3.0) – Depth values larger than depth_trunc gets truncated to 0. The depth values will first be scaled and then truncated.
    RGBDImage.create_from_color_and_depth(color, depth, depth_scale=1000.0, depth_trunc=3.0, convert_rgb_to_intensity=True)
    
  5. 网格提取or点云提取

    在完成TSDF的intergrate之后,可以从TSDF中提取出Mesh or PointCloud or VoxelGrid。

    voxel_grid = volume.extract_voxel_point_cloud()
    mesh = volume.extract_triangle_mesh()
    

    更多提取格式可以参考:http://www.open3d.org/docs/release/python_api/open3d.pipelines.integration.ScalableTSDFVolume.html。