Integrate Scene

シーン統合

システムの最後のステップは、すべてのRGBD画像を単一のTSDFボリュームに統合し、結果としてメッシュを抽出することである。

Input arguments

入力引数

このプログラムは、python run_system.py [config_file] --integrateとして実行される。 ここで[config_file]として指定するファイル(例えばReconstructionディレクトリのconfig/tutorial.json)の["path_dataset"]で指定するディレクトリ(例えばdataset/tutorial/)には、同期し位置合わせされるフレームがある画像と深度のディレクトリがなければならない。 [config_file]として指定するファイルにオプションの引数["path_intrinsic"]がある場合、これはカメラ固有行列(詳細についてはカメラ固有行列の読み込みを参照のこと)が記録されているjsonファイルへのパスである。これが指定されていない場合は、PrimeSense工場設定値が使用される。

注: PrimesenseはKinectやXtionで使われている3Dセンサの開発元でAppleが2013年に買収した。


次はexamples/Python/ReconstructionSystem/integrate_scene.pyで定義されている関数runであり、これがメイン関数である。まず["path_intrinsic"]で指定されるファイル(ない場合は、Open3Dのcamera.PinholeCameraIntrinsicParameters.PrimeSenseDefaultを使用)からカメラ固有行列を読み込み、scalable_integrate_rgb_frames関数に渡している。

In [ ]:
def run(config):
    print("integrate the whole RGBD sequence using estimated camera pose.")
    if config["path_intrinsic"]:
        intrinsic = o3d.io.read_pinhole_camera_intrinsic(
            config["path_intrinsic"])
    else:
        intrinsic = o3d.camera.PinholeCameraIntrinsic(
            o3d.camera.PinholeCameraIntrinsicParameters.PrimeSenseDefault)
    scalable_integrate_rgb_frames(config["path_dataset"], intrinsic, config)

Integrate RGBD frames

RGBDフレームの統合

examples/Python/ReconstructionSystem/integrate_scene.pyファイルで定義されている関数:

In [ ]:
# examples/Python/ReconstructionSystem/integrate_scene.py
def scalable_integrate_rgb_frames(path_dataset, intrinsic, config):
    poses = []
    [color_files, depth_files] = get_rgbd_file_lists(path_dataset)
    n_files = len(color_files)
    n_fragments = int(math.ceil(float(n_files) / \
            config['n_frames_per_fragment']))
    volume = o3d.integration.ScalableTSDFVolume(
        voxel_length=config["tsdf_cubic_size"] / 512.0,
        sdf_trunc=0.04,
        color_type=o3d.integration.TSDFVolumeColorType.RGB8)

    pose_graph_fragment = o3d.io.read_pose_graph(
        join(path_dataset, config["template_refined_posegraph_optimized"]))

    for fragment_id in range(len(pose_graph_fragment.nodes)):
        pose_graph_rgbd = o3d.io.read_pose_graph(
            join(path_dataset,
                 config["template_fragment_posegraph_optimized"] % fragment_id))

        for frame_id in range(len(pose_graph_rgbd.nodes)):
            frame_id_abs = fragment_id * \
                    config['n_frames_per_fragment'] + frame_id
            print(
                "Fragment %03d / %03d :: integrate rgbd frame %d (%d of %d)." %
                (fragment_id, n_fragments - 1, frame_id_abs, frame_id + 1,
                 len(pose_graph_rgbd.nodes)))
            rgbd = read_rgbd_image(color_files[frame_id_abs],
                                   depth_files[frame_id_abs], False, config)
            pose = np.dot(pose_graph_fragment.nodes[fragment_id].pose,
                          pose_graph_rgbd.nodes[frame_id].pose)
            volume.integrate(rgbd, intrinsic, np.linalg.inv(pose))
            poses.append(pose)

    mesh = volume.extract_triangle_mesh()
    mesh.compute_vertex_normals()
    if config["debug_mode"]:
        o3d.visualization.draw_geometries([mesh])

この関数は、最初にフラグメント作成フラグメントの位置合わせの両方からアライメント結果を読み込み、次にグローバルスペース内の各RGBD画像のポーズを計算する。 その後、RGBD統合を使用してRGBD画像が統合される。

Results

結果

以下はプログラムのログである。(注:これらは元サイトからのもの。白井の環境では8コアCPUで4分32秒ほどかかっている)

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%

以下の画像は最終的なシーン再構築を表している。

http://www.open3d.org/docs/release/_images/scene1.png

In [ ]:
# 確認用コード
import numpy as np
import open3d as o3d

pcd = o3d.io.read_point_cloud("../ReconstructionSystem/dataset/tutorial/scene/integrated.ply")
o3d.visualization.draw_geometries([pcd])

白井が実行した結果は…ゴミが残っている。

Integrated.png