File size: 1,872 Bytes
709cfd2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
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