def rot90(keypoints, rotation_permutation=None, scope=None):
  """Rotates the keypoints counter-clockwise by 90 degrees.

  Args:
    keypoints: a tensor of shape [num_instances, num_keypoints, 2]
    rotation_permutation:  integer list or rank 1 int32 tensor containing the
      keypoint flip permutation. This specifies the mapping from original
      keypoint indices to the rotated keypoint indices. This is used primarily
      for keypoints that are not rotation invariant.
      Default to None or empty list to keep the original order after rotation.
    scope: name scope.
  Returns:
    new_keypoints: a tensor of shape [num_instances, num_keypoints, 2]
  """
  with tf.name_scope(scope, 'Rot90'):
    keypoints = tf.transpose(keypoints, [1, 0, 2])
    if rotation_permutation:
      keypoints = tf.gather(keypoints, rotation_permutation)
    v, u = tf.split(value=keypoints[:, :, ::-1], num_or_size_splits=2, axis=2)
    v = 1.0 - v
    new_keypoints = tf.concat([v, u], 2)
    new_keypoints = tf.transpose(new_keypoints, [1, 0, 2])
    return new_keypoints
Rotates the keypoints counter-clockwise by 90 degrees.

  Args:
    keypoints: a tensor of shape [num_instances, num_keypoints, 2]
    rotation_permutation:  integer list or rank 1 int32 tensor containing the
      keypoint flip permutation. This specifies the mapping from original
      keypoint indices to the rotated keypoint indices. This is used primarily
      for keypoints that are not rotation invariant.
      Default to None or empty list to keep the original order after rotation.
    scope: name scope.
  Returns:
    new_keypoints: a tensor of shape [num_instances, num_keypoints, 2]
  
inference_api/src/main/object_detection/core/keypoint_ops.py