class_docstr: scale+rotation
class_docstr_tok: ["scale+rotation"]
code: def __call__(self, img, target):
      src_xmin, src_ymin, src_xmax, src_ymax = adjust_box(
          *target["box"], fixed_size=self.fixed_size
      )
      src_w = src_xmax - src_xmin
      src_h = src_ymax - src_ymin
      src_center = np.array(
          [(src_xmin + src_xmax) / 2, (src_ymin + src_ymax) / 2]
      )
      src_p2 = src_center + np.array([0, -src_h / 2])  # top middle
      src_p3 = src_center + np.array([src_w / 2, 0])  # right middle
  
      dst_center = np.array(
          [(self.fixed_size[1] - 1) / 2, (self.fixed_size[0] - 1) / 2]
      )
      dst_p2 = np.array([(self.fixed_size[1] - 1) / 2, 0])  # top middle
      dst_p3 = np.array(
          [self.fixed_size[1] - 1, (self.fixed_size[0] - 1) / 2]
      )  # right middle
  
      if self.scale is not None:
          scale = random.uniform(*self.scale)
          src_w = src_w * scale
          src_h = src_h * scale
          src_p2 = src_center + np.array([0, -src_h / 2])  # top middle
          src_p3 = src_center + np.array([src_w / 2, 0])  # right middle
  
      if self.rotation is not None:
          angle = random.randint(*self.rotation)  # 角度制
          angle = angle / 180 * math.pi  # 弧度制
          src_p2 = src_center + np.array(
              [
                  src_h / 2 * math.sin(angle),
                  -src_h / 2 * math.cos(angle),
              ]
          )
          src_p3 = src_center + np.array(
              [src_w / 2 * math.cos(angle), src_w / 2 * math.sin(angle)]
          )
  
      src = np.stack([src_center, src_p2, src_p3]).astype(np.float32)
      dst = np.stack([dst_center, dst_p2, dst_p3]).astype(np.float32)
  
      trans = cv2.getAffineTransform(src, dst)  # 计算正向仿射变换矩阵
      dst /= 4  # 网络预测的heatmap尺寸是输入图像的1/4
      reverse_trans = cv2.getAffineTransform(
          dst, src
      )  # 计算逆向仿射变换矩阵，方便后续还原
  
      # 对图像进行仿射变换
      resize_img = cv2.warpAffine(
          img,
          trans,
          tuple(self.fixed_size[::-1]),  # [w, h]
          flags=cv2.INTER_LINEAR,
      )
  
      if "keypoints" in target:
          kps = target["keypoints"]
          mask = np.logical_and(kps[:, 0] != 0, kps[:, 1] != 0)
          kps[mask] = affine_points(kps[mask], trans)
          target["keypoints"] = kps
  
      # import matplotlib.pyplot as plt
      # from draw_utils import draw_keypoints
      # resize_img = draw_keypoints(resize_img, target["keypoints"])
      # plt.imshow(resize_img)
      # plt.show()
  
      target["trans"] = trans
      target["reverse_trans"] = reverse_trans
      return resize_img, target
  
imports: import math
  import random
  from typing import Tuple
  import cv2
  import numpy
  import torch
  from torchvision.transforms import functional
  import matplotlib.pyplot
label_desc: Use image node_id 2 for calling the AffineTransform obj's underlying member method code with example usage: obj.__call__(img, target) and returns: resize_img,  target