code: def _get_perspective_transform(
      angle: float,
      width: int,
      height: int,
      focal: float,
      dist: float,
      crop_percent: float,
      crop_off_x: float,
      crop_off_y: float,
      pts: Optional[np.ndarray] = None,
  ) -> Tuple[np.ndarray, int, int]:
      """
      Computes parameters for perspective transform.
  
      :param angle: Angle to rotate.
      :param width: Width of image.
      :param height: Height of image.
      :param focal: Focal length.
      :param dist: Distance for transform.
      :param crop_percent: Percentage for cropping.
      :param crop_off_x: Cropping x offset.
      :param crop_off_y: Cropping y offset.
      :param pts: pts to include in the crop.
      :return: perspective transform matrix, crop width, crop_height
      """
      angle = math.radians(angle)
      x_cam_off = width / 2 - math.sin(angle) * dist
      z_cam_off = -math.cos(angle) * dist
      y_cam_off = height / 2
  
      rot_mat = np.array(
          [
              [math.cos(angle), 0, -math.sin(angle), 0],
              [0, 1, 0, 0],
              [math.sin(angle), 0, math.cos(angle), 0],
              [0, 0, 0, 1],
          ]
      )
      c_mat = np.array(
          [
              [1, 0, 0, -x_cam_off],
              [0, 1, 0, -y_cam_off],
              [0, 0, 1, -z_cam_off],
              [0, 0, 0, 1],
          ]
      )
  
      rt_mat = np.matmul(rot_mat, c_mat)
  
      h_mat = np.array(
          [
              [
                  focal * rt_mat[0, 0],
                  focal * rt_mat[0, 1],
                  focal * rt_mat[0, 3],
              ],
              [
                  focal * rt_mat[1, 0],
                  focal * rt_mat[1, 1],
                  focal * rt_mat[1, 3],
              ],
              [rt_mat[2, 0], rt_mat[2, 1], rt_mat[2, 3]],
          ]
      )
  
      x_off, y_off, crop_size = get_offset_and_crop_size(
          width,
          height,
          h_mat,
          crop_percent,
          crop_off_x,
          crop_off_y,
          focal / dist,
          pts,
      )
  
      affine_mat = np.array([[1, 0, x_off], [0, 1, y_off], [0, 0, 1]])
      perspective_mat = np.matmul(affine_mat, h_mat)
  
      if height > width:  # tall and narrow
          crop_x = int(crop_size)
          crop_y = int(round(crop_size / width * height))
      else:  # wide and short or square
          crop_y = int(crop_size)
          crop_x = int(round(crop_size / height * width))
  
      return perspective_mat, crop_x, crop_y
  
imports: from typing import Optional, Tuple, Union, TYPE_CHECKING, List
  import math
  import numpy
  from art.estimators.estimator import BaseEstimator
  from art.estimators.classification import ClassifierMixin
  from art.utils import get_labels_np_array
label_desc: Use image node_id 11 for calling a global function with example usage: _get_perspective_transform(angle, width, height, focal, dist, crop_percent, crop_off_x, crop_off_y, pts) and returns: perspective_mat,  crop_x,  crop_y