code: def random_affine(
      img,
      targets=(),
      degrees=10,
      translate=0.1,
      scale=0.1,
      shear=10,
      border=0,
  ):
      """随机旋转，缩放，平移以及错切"""
      # torchvision.transforms.RandomAffine(degrees=(-10, 10), translate=(.1, .1), scale=(.9, 1.1), shear=(-10, 10))
      # https://medium.com/uruvideo/dataset-augmentation-with-random-homographies-a8f4b44830d4
      # 这里可以参考我写的博文: https://blog.csdn.net/qq_37541097/article/details/119420860
      # targets = [cls, xyxy]
  
      # 最终输出的图像尺寸，等于img4.shape / 2
      height = img.shape[0] + border * 2
      width = img.shape[1] + border * 2
  
      # Rotation and Scale
      # 生成旋转以及缩放矩阵
      R = np.eye(3)  # 生成对角阵
      a = random.uniform(-degrees, degrees)  # 随机旋转角度
      s = random.uniform(1 - scale, 1 + scale)  # 随机缩放因子
      R[:2] = cv2.getRotationMatrix2D(
          angle=a, center=(img.shape[1] / 2, img.shape[0] / 2), scale=s
      )
  
      # Translation
      # 生成平移矩阵
      T = np.eye(3)
      T[0, 2] = (
          random.uniform(-translate, translate) * img.shape[0] + border
      )  # x translation (pixels)
      T[1, 2] = (
          random.uniform(-translate, translate) * img.shape[1] + border
      )  # y translation (pixels)
  
      # Shear
      # 生成错切矩阵
      S = np.eye(3)
      S[0, 1] = math.tan(
          random.uniform(-shear, shear) * math.pi / 180
      )  # x shear (deg)
      S[1, 0] = math.tan(
          random.uniform(-shear, shear) * math.pi / 180
      )  # y shear (deg)
  
      # Combined rotation matrix
      M = S @ T @ R  # ORDER IS IMPORTANT HERE!!
      if (border != 0) or (M != np.eye(3)).any():  # image changed
          # 进行仿射变化
          img = cv2.warpAffine(
              img,
              M[:2],
              dsize=(width, height),
              flags=cv2.INTER_LINEAR,
              borderValue=(114, 114, 114),
          )
  
      # Transform label coordinates
      n = len(targets)
      if n:
          # warp points
          xy = np.ones((n * 4, 3))
          xy[:, :2] = targets[:, [1, 2, 3, 4, 1, 4, 3, 2]].reshape(
              n * 4, 2
          )  # x1y1, x2y2, x1y2, x2y1
          # [4*n, 3] -> [n, 8]
          xy = (xy @ M.T)[:, :2].reshape(n, 8)
  
          # create new boxes
          # 对transform后的bbox进行修正(假设变换后的bbox变成了菱形，此时要修正成矩形)
          x = xy[:, [0, 2, 4, 6]]  # [n, 4]
          y = xy[:, [1, 3, 5, 7]]  # [n, 4]
          xy = (
              np.concatenate((x.min(1), y.min(1), x.max(1), y.max(1)))
              .reshape(4, n)
              .T
          )  # [n, 4]
  
          # reject warped points outside of image
          # 对坐标进行裁剪，防止越界
          xy[:, [0, 2]] = xy[:, [0, 2]].clip(0, width)
          xy[:, [1, 3]] = xy[:, [1, 3]].clip(0, height)
          w = xy[:, 2] - xy[:, 0]
          h = xy[:, 3] - xy[:, 1]
  
          # 计算调整后的每个box的面积
          area = w * h
          # 计算调整前的每个box的面积
          area0 = (targets[:, 3] - targets[:, 1]) * (
              targets[:, 4] - targets[:, 2]
          )
          # 计算每个box的比例
          ar = np.maximum(
              w / (h + 1e-16), h / (w + 1e-16)
          )  # aspect ratio
          # 选取长宽大于4个像素，且调整前后面积比例大于0.2，且比例小于10的box
          i = (
              (w > 4)
              & (h > 4)
              & (area / (area0 * s + 1e-16) > 0.2)
              & (ar < 10)
          )
  
          targets = targets[i]
          targets[:, 1:5] = xy[i]
  
      return img, targets
  
imports: import math
  import os
  import random
  import shutil
  from pathlib import Path
  import cv2
  import numpy
  import torch
  from PIL import Image, ExifTags
  from torch.utils.data import Dataset
  from tqdm import tqdm
  from build_utils.utils import xyxy2xywh, xywh2xyxy
label_desc: Use image node_id 4 for calling a global function with example usage: random_affine(img, targets, degrees, translate, scale, shear, border) and returns: img,  targets