def gaps_depth_image_to_cam_image(depth_image, xfov=0.5): """Converts a GAPS depth image to a camera-space image. Args: depth_image: Numpy array with shape [height, width] or [height, width, 1]. The depth in units (not in 1000ths of units, which is what GAPS writes). xfov: The xfov of the image in the GAPS format (half-angle in radians). Returns: cam_image: array with shape [height, width, 3]. """ height, width = depth_image.shape[0:2] depth_image = np.reshape(depth_image, [height, width]) pixel_coords = np_util.make_coordinate_grid(height, width, is_screen_space=False, is_homogeneous=False) nic_x = 2 * pixel_coords[:, :, 0] - 1.0 nic_y = 2 * pixel_coords[:, :, 1] - 1.0 nic_d = -depth_image aspect = height / float(width) yfov = math.atan(aspect * math.tan(xfov)) intrinsics_00 = 1.0 / math.tan(xfov) intrinsics_11 = 1.0 / math.tan(yfov) cam_x = nic_x * -nic_d / intrinsics_00 cam_y = nic_y * nic_d / intrinsics_11 cam_z = nic_d return np.stack([cam_x, cam_y, cam_z], axis=2)
def depth_to_cam_np(im, xfov=0.5): """Converts a gaps depth image to camera space.""" im = _unbatch(im) height, width, _ = im.shape pixel_coords = np_util.make_coordinate_grid( height, width, is_screen_space=False, is_homogeneous=False) nic_x = np.reshape(pixel_coords[:, :, 0], [height, width]) nic_y = np.reshape(pixel_coords[:, :, 1], [height, width]) # GAPS nic coordinates have an origin at the center of the image, not # in the corner: nic_x = 2 * nic_x - 1.0 nic_y = 2 * nic_y - 1.0 nic_d = -np.reshape(im, [height, width]) aspect = height / float(width) yfov = math.atan(aspect * math.tan(xfov)) intrinsics_00 = 1.0 / math.tan(xfov) intrinsics_11 = 1.0 / math.tan(yfov) cam_x = nic_x * -nic_d / intrinsics_00 cam_y = nic_y * nic_d / intrinsics_11 cam_z = nic_d cam_xyz = np.stack([cam_x, cam_y, cam_z], axis=2) return cam_xyz
def gaps_depth_image_to_cam_image(depth_image, xfov): """Converts a GAPS depth image tensor to a camera-space image tensor. Args: depth_image: Tensor with shape [batch_size, height, width, 1]. xfov: Scalar or tensor with shape [1] or [batch_size]. Returns: cam_image: Tensor with shape [batch_size, height, width, 3]. """ batch_size, height, width = depth_image.get_shape().as_list()[:3] depth_image = tf.ensure_shape(depth_image, [batch_size, height, width, 1]) if isinstance(xfov, float): xfov = tf.constant([xfov], dtype=tf.float32) xfov = tf.tile(xfov, [batch_size]) else: xfov = tf.reshape(xfov, [batch_size]) # if xfov.get_shape().as_list()[0] == 1: # xfov = tf.tile(xfov, [batch_size]) # else: # assert xfov.get_shape().as_list()[0] == batch_size pixel_coords = np_util.make_coordinate_grid(height, width, is_screen_space=False, is_homogeneous=False) # Values should go from -1 -> 1, not from 0 -> 1: nic_x = np_util.batch_np(2 * pixel_coords[:, :, 0:1] - 1.0, batch_size) nic_y = np_util.batch_np(2 * pixel_coords[:, :, 1:2] - 1.0, batch_size) nic_d = -depth_image aspect = height / float(width) tan_xfov = tf.math.tan(xfov) yfov = tf.math.atan(aspect * tan_xfov) intrinsics_00 = tf.reshape(1.0 / tan_xfov, [batch_size, 1, 1, 1]) intrinsics_11 = tf.reshape(1.0 / tf.math.tan(yfov), [batch_size, 1, 1, 1]) cam_x = nic_x * -nic_d / intrinsics_00 cam_y = nic_y * nic_d / intrinsics_11 cam_z = nic_d return tf.concat([cam_x, cam_y, cam_z], axis=3)
def depth_image_to_xyz_image(depth_images, world_to_camera, xfov=0.5): """Converts GAPS depth images to world space.""" batch_size, height, width, channel_count = depth_images.get_shape().as_list() assert channel_count == 1 camera_to_world_mat = tf.matrix_inverse(world_to_camera) pixel_coords = np_util.make_coordinate_grid( height, width, is_screen_space=False, is_homogeneous=False) nic_x = np.tile( np.reshape(pixel_coords[:, :, 0], [1, height, width]), [batch_size, 1, 1]) nic_y = np.tile( np.reshape(pixel_coords[:, :, 1], [1, height, width]), [batch_size, 1, 1]) nic_x = 2 * nic_x - 1.0 nic_y = 2 * nic_y - 1.0 nic_d = -tf.reshape(depth_images, [batch_size, height, width]) aspect = height / float(width) yfov = math.atan(aspect * math.tan(xfov)) intrinsics_00 = 1.0 / math.tan(xfov) intrinsics_11 = 1.0 / math.tan(yfov) nic_xyz = tf.stack([nic_x, nic_y, nic_d], axis=3) flat_nic_xyz = tf.reshape(nic_xyz, [batch_size, height * width, 3]) camera_x = (nic_x) * -nic_d / intrinsics_00 camera_y = (nic_y) * nic_d / intrinsics_11 camera_z = nic_d homogeneous_coord = tf.ones_like(camera_z) camera_xyz = tf.stack([camera_x, camera_y, camera_z, homogeneous_coord], axis=3) flat_camera_xyzw = tf.reshape(camera_xyz, [batch_size, height * width, 4]) flat_world_xyz = tf.matmul( flat_camera_xyzw, camera_to_world_mat, transpose_b=True) world_xyz = tf.reshape(flat_world_xyz, [batch_size, height, width, 4]) world_xyz = world_xyz[:, :, :, :3] return world_xyz, flat_camera_xyzw[:, :, :3], flat_nic_xyz
def depth_image_to_cam_image(depth_image, fx=585.0, fy=585.0, cx=255.5, cy=255.5): """Converts a GAPS depth image to a camera-space image. Args: depth_image: Numpy array with shape [height, width] or [height, width, 1]. The depth in units (not in 1000ths of units, which is what GAPS writes). fx: The x focal-length. Float. fy: The y focal-length. Float. cx: The x center. Float. cy: The y center. Float. Returns: cam_image: array with shape [height, width, 3]. """ is_invalid = np.squeeze(depth_image == 0.0) height, width = depth_image.shape[0:2] depth_image = np.reshape(depth_image, [height, width]) pixel_coords = np_util.make_coordinate_grid( height, width, is_screen_space=True, is_homogeneous=False) # log.info(np.max(pixel_coords)) # log.info(np.min(pixel_coords)) nic_x = pixel_coords[:, :, 0] nic_y = pixel_coords[:, :, 1] nic_d = -depth_image # cam_x = (nic_x - 255.5) * (-nic_d) / 585.0 # cam_y = (nic_y - 255.5) * (nic_d) / 585.0 cam_x = (nic_x - cx) * (-nic_d) / fx cam_y = (nic_y - cy) * nic_d / fy cam_z = nic_d cam = np.stack([cam_x, cam_y, cam_z], axis=-1) cam[is_invalid, :] = 0.0 return cam