gangweix's picture
Upload 26 files
709cfd2 verified
import numpy as np
import open3d as o3d
def depth2pcd(depth, intrinsic, color=None, input_mask=None, ret_pcd=False):
"""
Convert a depth map into a 3D point cloud.
Args:
depth (np.ndarray): (H, W) depth map in meters.
intrinsic (np.ndarray): (3, 3) camera intrinsic matrix.
color (np.ndarray, optional): (H, W, 3) RGB image aligned with the depth map.
input_mask (np.ndarray, optional): (H, W) boolean mask indicating valid pixels.
ret_pcd (bool, optional): If True, returns an Open3D PointCloud object;
otherwise returns NumPy arrays.
Returns:
- If ret_pcd=True: returns `o3d.geometry.PointCloud()`
- Otherwise: returns (N, 3) point coordinates and (N, 3) color arrays.
"""
H, W = depth.shape
x, y = np.meshgrid(np.arange(W), np.arange(H))
xx, yy = x.reshape(-1), y.reshape(-1)
zz = depth.reshape(-1)
# Create a valid pixel mask
mask = np.ones_like(zz, dtype=bool)
if input_mask is not None:
mask &= input_mask.reshape(-1)
# Form homogeneous pixel coordinates
pixels = np.stack([xx, yy, np.ones_like(xx)], axis=1)
# Back-project pixels into 3D camera coordinates
points = pixels * zz[:, None]
points = np.dot(points, np.linalg.inv(intrinsic).T)
# Keep only valid points
points = points[mask]
# Process color information
if color is not None:
color = color.astype(np.float32) / 255.0
colors = color.reshape(-1, 3)[mask]
else:
colors = None
# Return Open3D point cloud or NumPy arrays
if ret_pcd:
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points)
if colors is not None:
pcd.colors = o3d.utility.Vector3dVector(colors)
return pcd
else:
return points, colors