Integrate scene

The final step of the system is to integrate all RGBD images into a single TSDF volume and extract a mesh as the result.

Input arguments

The script runs with python run_system.py [config] --integrate. In [config], ["path_dataset"] should have subfolders image and depth in which frames are synchronized and aligned. In [config], the optional argument ["path_intrinsic"] specifies path to a json file that has a camera intrinsic matrix (See /tutorial/pipelines/rgbd_odometry.ipynb#read-camera-intrinsic for details). If it is not given, the PrimeSense factory setting is used instead.

Integrate RGBD frames

38# examples/python/reconstruction_system/integrate_scene.py
39sys.path.append(os.path.dirname(os.path.abspath(__file__)))
40from make_fragments import read_rgbd_image
41
42
43def scalable_integrate_rgb_frames(path_dataset, intrinsic, config):
44    poses = []
45    [color_files, depth_files] = get_rgbd_file_lists(path_dataset)
46    n_files = len(color_files)
47    n_fragments = int(math.ceil(float(n_files) / \
48            config['n_frames_per_fragment']))
49    volume = o3d.pipelines.integration.ScalableTSDFVolume(
50        voxel_length=config["tsdf_cubic_size"] / 512.0,
51        sdf_trunc=0.04,
52        color_type=o3d.pipelines.integration.TSDFVolumeColorType.RGB8)
53
54    pose_graph_fragment = o3d.io.read_pose_graph(
55        join(path_dataset, config["template_refined_posegraph_optimized"]))
56
57    for fragment_id in range(len(pose_graph_fragment.nodes)):
58        pose_graph_rgbd = o3d.io.read_pose_graph(
59            join(path_dataset,
60                 config["template_fragment_posegraph_optimized"] % fragment_id))
61
62        for frame_id in range(len(pose_graph_rgbd.nodes)):
63            frame_id_abs = fragment_id * \
64                    config['n_frames_per_fragment'] + frame_id
65            print(
66                "Fragment %03d / %03d :: integrate rgbd frame %d (%d of %d)." %
67                (fragment_id, n_fragments - 1, frame_id_abs, frame_id + 1,
68                 len(pose_graph_rgbd.nodes)))
69            rgbd = read_rgbd_image(color_files[frame_id_abs],
70                                   depth_files[frame_id_abs], False, config)
71            pose = np.dot(pose_graph_fragment.nodes[fragment_id].pose,
72                          pose_graph_rgbd.nodes[frame_id].pose)
73            volume.integrate(rgbd, intrinsic, np.linalg.inv(pose))
74            poses.append(pose)
75

This function first reads the alignment results from both Make fragments and Register fragments, then computes the pose of each RGBD image in the global space. After that, RGBD images are integrated using /tutorial/pipelines/rgbd_integration.ipynb.

Results

This is a printed log from the volume integration script.

Fragment 000 / 013 :: integrate rgbd frame 0 (1 of 100).
Fragment 000 / 013 :: integrate rgbd frame 1 (2 of 100).
Fragment 000 / 013 :: integrate rgbd frame 2 (3 of 100).
Fragment 000 / 013 :: integrate rgbd frame 3 (4 of 100).
:
Fragment 013 / 013 :: integrate rgbd frame 1360 (61 of 64).
Fragment 013 / 013 :: integrate rgbd frame 1361 (62 of 64).
Fragment 013 / 013 :: integrate rgbd frame 1362 (63 of 64).
Fragment 013 / 013 :: integrate rgbd frame 1363 (64 of 64).
Writing PLY: [========================================] 100%

The following image shows the final scene reconstruction.

../../_images/scene.png