code: def affine(
      img: Tensor,
      angle: float,
      translate: List[int],
      scale: float,
      shear: List[float],
      interpolation: InterpolationMode = InterpolationMode.NEAREST,
      fill: Optional[List[float]] = None,
      center: Optional[List[int]] = None,
  ) -> Tensor:
      """Apply affine transformation on the image keeping image center invariant.
      If the image is torch Tensor, it is expected
      to have [..., H, W] shape, where ... means an arbitrary number of leading dimensions.
  
      Args:
          img (PIL Image or Tensor): image to transform.
          angle (number): rotation angle in degrees between -180 and 180, clockwise direction.
          translate (sequence of integers): horizontal and vertical translations (post-rotation translation)
          scale (float): overall scale
          shear (float or sequence): shear angle value in degrees between -180 to 180, clockwise direction.
              If a sequence is specified, the first value corresponds to a shear parallel to the x-axis, while
              the second value corresponds to a shear parallel to the y-axis.
          interpolation (InterpolationMode): Desired interpolation enum defined by
              :class:`torchvision.transforms.InterpolationMode`. Default is ``InterpolationMode.NEAREST``.
              If input is Tensor, only ``InterpolationMode.NEAREST``, ``InterpolationMode.BILINEAR`` are supported.
              The corresponding Pillow integer constants, e.g. ``PIL.Image.BILINEAR`` are accepted as well.
          fill (sequence or number, optional): Pixel fill value for the area outside the transformed
              image. If given a number, the value is used for all bands respectively.
  
              .. note::
                  In torchscript mode single int/float value is not supported, please use a sequence
                  of length 1: ``[value, ]``.
          center (sequence, optional): Optional center of rotation. Origin is the upper left corner.
              Default is the center of the image.
  
      Returns:
          PIL Image or Tensor: Transformed image.
      """
      if not torch.jit.is_scripting() and not torch.jit.is_tracing():
          _log_api_usage_once(affine)
  
      if isinstance(interpolation, int):
          interpolation = _interpolation_modes_from_int(interpolation)
      elif not isinstance(interpolation, InterpolationMode):
          raise TypeError(
              "Argument interpolation should be a InterpolationMode or a corresponding Pillow integer constant"
          )
  
      if not isinstance(angle, (int, float)):
          raise TypeError("Argument angle should be int or float")
  
      if not isinstance(translate, (list, tuple)):
          raise TypeError("Argument translate should be a sequence")
  
      if len(translate) != 2:
          raise ValueError(
              "Argument translate should be a sequence of length 2"
          )
  
      if scale <= 0.0:
          raise ValueError("Argument scale should be positive")
  
      if not isinstance(shear, (numbers.Number, (list, tuple))):
          raise TypeError(
              "Shear should be either a single value or a sequence of two values"
          )
  
      if isinstance(angle, int):
          angle = float(angle)
  
      if isinstance(translate, tuple):
          translate = list(translate)
  
      if isinstance(shear, numbers.Number):
          shear = [shear, 0.0]
  
      if isinstance(shear, tuple):
          shear = list(shear)
  
      if len(shear) == 1:
          shear = [shear[0], shear[0]]
  
      if len(shear) != 2:
          raise ValueError(
              f"Shear should be a sequence containing two values. Got {shear}"
          )
  
      if center is not None and not isinstance(center, (list, tuple)):
          raise TypeError("Argument center should be a sequence")
  
      _, height, width = get_dimensions(img)
      if not isinstance(img, torch.Tensor):
          # center = (width * 0.5 + 0.5, height * 0.5 + 0.5)
          # it is visually better to estimate the center without 0.5 offset
          # otherwise image rotated by 90 degrees is shifted vs output image of torch.rot90 or F_t.affine
          if center is None:
              center = [width * 0.5, height * 0.5]
          matrix = _get_inverse_affine_matrix(
              center, angle, translate, scale, shear
          )
          pil_interpolation = pil_modes_mapping[interpolation]
          return F_pil.affine(
              img,
              matrix=matrix,
              interpolation=pil_interpolation,
              fill=fill,
          )
  
      center_f = [0.0, 0.0]
      if center is not None:
          _, height, width = get_dimensions(img)
          # Center values should be in pixel coordinates but translated such that (0, 0) corresponds to image center.
          center_f = [
              1.0 * (c - s * 0.5)
              for c, s in zip(center, [width, height])
          ]
  
      translate_f = [1.0 * t for t in translate]
      matrix = _get_inverse_affine_matrix(
          center_f, angle, translate_f, scale, shear
      )
      return F_t.affine(
          img,
          matrix=matrix,
          interpolation=interpolation.value,
          fill=fill,
      )
  
imports: import math
  import numbers
  import sys
  import warnings
  from enum import Enum
  from typing import Any, List, Optional, Tuple, Union
  import numpy
  import torch
  from PIL import Image
  from torch import Tensor
  from ..utils import _log_api_usage_once
  from .None import _functional_pil, _functional_tensor
label_desc: Use image node_id 31 for calling a global function with example usage: affine(img, angle, translate, scale, shear, interpolation, fill, center) and returns: F_t, F_pil