code: def affine(
      tens: Tensor,
      angle: Union[float, int],
      translate: Union[List[int], Tuple[int]],
      scale: float,
      shear: float,
      interpolation: str = "bilinear",
      mode: Union[str, int] = 0,
      fillcolor: int = 0,
  ) -> Tensor:
      """
          Apply affine transformation on the image keeping image center invariant.
  
      Args:
          tens (Tensor): Any valid ``caer.Tensor``.
          angle (float or int): Rotation angle in degrees between -180 and 180, clockwise direction.
          translate (list or tuple of integers): Horizontal and vertical translations (post-rotation translation)
          scale (float): Overall scale
          shear (float): Shear angle value in degrees between -180 to 180, clockwise direction.
          interpolation (int, str): Interpolation to use for resizing. Defaults to `"bilinear"`.
                  Supports `"bilinear"`, `"bicubic"`, `"area"`, `"nearest"`.
          mode (int, str): Method for filling in border regions.
                  Defaults to ``constant`` meaning areas outside the image are filled with a value (val, default 0).
                  Supports ``"replicate"``, ``"reflect"``, ``"reflect-101"``.
          fillcolor (int): Optional fill color for the area outside the transform in the output image. Default: 0
      """
  
      tens = to_tensor(tens, enforce_tensor=True)
      cspace = tens.cspace
  
      assert (
          isinstance(translate, (tuple, list)) and len(translate) == 2
      ), "Argument translate should be a list or tuple of length 2"
  
      assert scale > 0.0, "Argument scale should be positive"
  
      interpolation_methods = {
          "nearest": 0,
          "0": 0,
          0: 0,  # 0
          "bilinear": 1,
          "1": 1,
          1: 1,  # 1
          "bicubic": 2,
          "2": 2,
          2: 2,  # 2
          "area": 3,
          "3": 3,
          3: 3,  # 3
      }
      border_methods = {
          "constant": 0,
          "0": 0,
          0: 0,  # 0
          "replicate": 1,
          "1": 1,
          1: 1,  # 1
          "reflect": 2,
          "2": 2,
          2: 2,  # 2
          "reflect-101": 4,
          "4": 4,
          4: 4,  # 4
      }
  
      if interpolation not in interpolation_methods:
          raise ValueError(
              "Specify a valid interpolation type - area/nearest/bicubic/bilinear"
          )
  
      if mode not in border_methods:
          raise ValueError(
              "Specify a valid border type - constant/replicate/reflect/reflect-101"
          )
  
      output_size = tens.shape[0:2]
      center = (tens.shape[1] * 0.5 + 0.5, tens.shape[0] * 0.5 + 0.5)
      matrix = _get_affine_matrix(
          center, angle, translate, scale, shear
      )
  
      tens = cv.warpAffine(
          tens,
          matrix,
          output_size[::-1],
          interpolation,
          borderMode=mode,
          borderValue=fillcolor,
      )
  
      return to_tensor(tens, cspace=cspace)
  
file_path: caer/caer/transforms/color.py
imports: import numpy
  import random
  import cv2
  import math
  from ..coreten import Tensor, to_tensor
  from ..annotations import Union, List, Tuple
  from .functional import is_list, _hls, _exposure_process
label_desc: Use image node_id 10 for calling a global function with example usage: affine(tens, angle, translate, scale, shear, interpolation, mode, fillcolor) and returns: to_tensor