Search code examples
pythonpoint-cloud-librarypoint-cloudsrealsenseopen3d

visualizing the pointcloud from realsense API or Open3D library


I have a depth frame from an Intel RealSense camera and I want to convert it to pointcloud and visualize the pointcloud. So far, as for creating the pointcloud given only the depth frame and camera intrinsics, I found the following two functions however I can't seem to find a way to visualize either one or store them as .ply file.

How should I visualize a pointcloud made this way?

method 1:

pointcloud = convert_depth_frame_to_pointcloud(original_depth_frame, color_intrinsics)

in which convert_depth_frame_to_pointcloud is a helper function from RealSense.

method 2 using Open3D library:

pcd = o3d.geometry.PointCloud.create_from_depth_image(original_depth_frame, color_intrinsics)
pcd.transform([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])
print(np.asarray(pcd.points)[1, :])  
o3d.visualization.draw_geometries([pcd])

Also, when using o3d, I get this error:

create_from_depth_image(): incompatible function arguments. The following argument types are supported:
    1. (depth: open3d::geometry::Image, intrinsic: open3d.cuda.pybind.camera.PinholeCameraIntrinsic, extrinsic: numpy.ndarray[float64[4, 4]] = array([[1., 0., 0., 0.],
       [0., 1., 0., 0.],
       [0., 0., 1., 0.],
       [0., 0., 0., 1.]]), depth_scale: float = 1000.0, depth_trunc: float = 1000.0, stride: int = 1, project_valid_depth_only: bool = True) -> open3d.cuda.pybind.geometry.PointCloud

Here the original_depth_frame is read:

frame = cv2.imread(os.path.join(args.depth_input_dir, imgs_dir[frame_idx]), cv2.IMREAD_ANYDEPTH)

where one depth image is like:

000248.png PNG 1280x720 1280x720+0+0 16-bit Grayscale Gray 567278B 0.000u 0:00.000

where color_intrinsics is:

def set_intrinsics(intrinsics_dict):
    intrinsics = rs.intrinsics()
    intrinsics.width = intrinsics_dict['width']
    intrinsics.height = intrinsics_dict['height']
    intrinsics.ppx = intrinsics_dict['ppx']
    intrinsics.ppy = intrinsics_dict['ppy']
    intrinsics.fx = intrinsics_dict['fx']
    intrinsics.fy = intrinsics_dict['fy']
    intrinsics.model = intrinsics_dict['model']
    intrinsics.coeffs = intrinsics_dict['coeffs']
    return intrinsics
color_intrinsics = set_intrinsics(camera['color_intrinsics'])

Using open3d I am able to create the pointcloud of a depth image in PNG format if I don't read it using opencv (however I need to do so as part of my code).

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

raw_depth = o3d.io.read_image('depth_images/000248.png')
pcd = o3d.geometry.PointCloud.create_from_depth_image(raw_depth, 
o3d.camera.PinholeCameraIntrinsic(
                                  o3d.camera.PinholeCameraIntrinsicParameters.PrimeSenseDefault)
                                , np.identity(4), depth_scale=1000.0, depth_trunc=1000.0)
pcd.transform([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])
print(np.asarray(pcd.points)[1,:])
o3d.visualization.draw_geometries([pcd])

^^ the code above produces a 3D pointcloud.


Solution

  • You would need to read your image similar as follows:

    import open3d as o3d
    import matplotlib.pyplot as plt
    import numpy as np
    
    raw_depth = o3d.io.read_image('depth_images/000248.png')
    pcd = o3d.geometry.PointCloud.create_from_depth_image(raw_depth, 
    o3d.camera.PinholeCameraIntrinsic(
                                      o3d.camera.PinholeCameraIntrinsicParameters.PrimeSenseDefault)
                                    , np.identity(4), depth_scale=1000.0, depth_trunc=1000.0)
    pcd.transform([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])
    print(np.asarray(pcd.points)[1,:])
    o3d.visualization.draw_geometries([pcd])