Spaces:
Running
on
Zero
Running
on
Zero
File size: 1,798 Bytes
cf7f9c0 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
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
u, v = np.meshgrid(np.arange(W), np.arange(H))
fx, fy = intrinsic[0,0], intrinsic[1,1]
cx, cy = intrinsic[0,2], intrinsic[1,2]
Z = depth.reshape(-1)
X = ((u.reshape(-1) - cx) / fx) * Z
Y = ((v.reshape(-1) - cy) / fy) * Z
points = np.stack([X, Y, Z], axis=1)
# mask valid points
mask = np.ones_like(Z, dtype=bool)
if input_mask is not None:
mask &= input_mask.reshape(-1)
# 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 |