code: def pcd_3d_to_pcd_2d_torch(
      pcd,
      intrinsic,
      extrinsic,
      size,
      keep_z,
      crop: bool = True,
      filter_neg: bool = True,
      norm_coord: bool = True,
      return_index: bool = False,
      valid_mask=None,
  ):
      assert isinstance(
          pcd, torch.Tensor
      ), f"cannot process data type: {type(pcd)}"
      assert isinstance(
          intrinsic, torch.Tensor
      ), f"cannot process data type: {type(intrinsic)}"
      assert isinstance(
          extrinsic, torch.Tensor
      ), f"cannot process data type: {type(extrinsic)}"
      assert (
          len(pcd.shape) == 3
          and pcd.shape[1] >= 3
          and pcd.shape[2] > pcd.shape[1]
      ), f"seems the input pcd is not a valid point cloud: {pcd.shape}"
      assert intrinsic.shape[1:] == (3, 3)
      if extrinsic.shape[1:] == (4, 4):
          extrinsic = extrinsic[:, 0:3, :]
      assert extrinsic.shape[1:] == (3, 4)
  
      if valid_mask is None:
          valid_mask = pcd.bool().all(dim=1)
      xyzw = torch.cat(
          [pcd[:, 0:3, :], torch.ones_like(pcd[:, 0:1, :])], axis=1
      )
      mvp_mat = torch.matmul(intrinsic, extrinsic)
      camera_points = torch.matmul(mvp_mat, xyzw)
      if filter_neg:
          valid_mask = valid_mask * (camera_points[:, 2, :] > 0.0)
      camera_points = valid_mask[:, None, :].float() * camera_points
      image_points = torch.zeros_like(camera_points)
      image_points = camera_points / camera_points[:, 2:3, :]
      image_points = image_points[:, :2, :]
      # clear nan
      image_points[
          torch.isnan(image_points)
          .any(dim=1)[:, None, :]
          .repeat(1, 2, 1)
      ] = 0
      size = size.float()
      if crop:
          valid_mask = (
              valid_mask
              * (image_points[:, 0, :] >= 0)
              * (image_points[:, 0, :] < (size[:, 1] - 1)[:, None])
              * (image_points[:, 0, :] >= 0)
              * (image_points[:, 1, :] < (size[:, 0] - 1)[:, None])
          )
      if norm_coord:
          image_points = (
              (image_points / torch.flip(size, [1])[..., None]) * 2
          ) - 1
      if keep_z:
          image_points = torch.cat(
              [image_points, camera_points[:, 2:3, :], pcd[:, 3:, :]],
              dim=1,
          )
      else:
          image_points = torch.cat([image_points, pcd[:, 3:, :]], dim=1)
      image_points = valid_mask[:, None, :].float() * image_points
      if return_index:
          return image_points, valid_mask
      return image_points
  
file_path: ml-neuman/geometry/pcd_projector.py
imports: import numpy
  import torch
label_desc: Use image node_id 2 for calling a global function with example usage: pcd_3d_to_pcd_2d_torch(pcd, intrinsic, extrinsic, size, keep_z, crop, filter_neg, norm_coord, return_index, valid_mask) and returns: image_points, image_points,  valid_mask