open3d python depth画像とRGB画像からpoint cloudを可視化する

入出力

入力画像

深度画像:16bit tiff
RGB画像:24bit RGB (8bit ×3) tiff
(Redwood Dataset をtiffに変換して入力)

出力画像

PLYファイル

全コード

import numpy as np
import matplotlib.pyplot as plt
import open3d as o3d
import os
import cv2

if __name__ == "__main__":
    os.chdir(os.path.dirname(os.path.abspath(__file__)))
    
    # Camera parameters:
    FX_DEPTH = 5.8262448167737955e02
    FY_DEPTH = 5.8269103270988637e02
    CX_DEPTH = 3.1304475870804731e02
    CY_DEPTH = 2.3844389626620386e02

    # Read depth and color image:
    depth_image = cv2.imread("./depth_00000.tif", cv2.IMREAD_UNCHANGED)
    rgb_image = cv2.imread("./rgb_00000.tif", cv2.IMREAD_UNCHANGED)
    rgb_image = cv2.cvtColor(rgb_image, cv2.COLOR_BGR2RGB)
    print(f"type(depth_image):{type(depth_image)}")
    print(f"type(rgb_image):{type(rgb_image)}")
    print(f"depth_image.shape:{depth_image.shape}")
    print(f"rgb_image.shape:{rgb_image.shape}")
    print(f"depth_image.dtype:{depth_image.dtype}")
    print(f"rgb_image.dtype:{rgb_image.dtype}")

    depth_image = depth_image.astype(np.int32)
    rgb_image = rgb_image.astype(np.uint8)

    color = o3d.geometry.Image(rgb_image)
    depth = o3d.geometry.Image(depth_image.astype(np.uint16))

    # Display depth and grayscale image:
    fig, axs = plt.subplots(1, 2)
    axs[0].imshow(depth, cmap="gray")
    axs[0].set_title("Depth image")
    axs[1].imshow(color)
    axs[1].set_title("RGB image")
    plt.show()

    # compute point cloud:
    # Both images has the same resolution
    height, width = depth_image.shape
    pinhole_camera_intrinsic = o3d.camera.PinholeCameraIntrinsic(
        width, height, FX_DEPTH, FY_DEPTH, CX_DEPTH, CY_DEPTH
    )
    rgbd = o3d.geometry.RGBDImage.create_from_color_and_depth(
        color, depth, convert_rgb_to_intensity=False
    )
    pcd_o3d = o3d.geometry.PointCloud.create_from_rgbd_image(
        rgbd, pinhole_camera_intrinsic
    )

    # Convert to Open3D.PointCLoud:
    pcd_o3d.transform([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])
    o3d.visualization.draw_geometries([pcd_o3d])
    o3d.io.write_point_cloud("test.ply", pcd_o3d)

出力例


RGB画像とDepth画像


Point Cloudの表示

注意点

  • 下記でconvert_rgb_to_intensity=Trueにすると、Point Cloud 表示がモノクロになる。

rgbd = o3d.geometry.RGBDImage.create_from_color_and_depth(
    color, depth, convert_rgb_to_intensity=False
)
  • 下記でo3d.geometry.Image形式に変換する際、uint8, uint16, or floatしか受け付けない。

depth = o3d.geometry.Image(depth_image.astype(np.uint16))
  • opencvでRGB画像を読み込むとBGRで読み込まれる。cv2.cvtColorで変換が必要

    rgb_image = cv2.imread("./rgb_00000.tif", cv2.IMREAD_UNCHANGED)
    rgb_image = cv2.cvtColor(rgb_image, cv2.COLOR_BGR2RGB)

参考


この記事が気に入ったらサポートをしてみませんか?