class_docstr: apply data augment to images and coords
  to achieve the flip, scale, rotate and half body transform effect for training image
  Args:
      trainsize (list):[w, h], Image target size
      upper_body_ids (list): The upper body joint ids
      flip_pairs (list): The left-right joints exchange order list
      pixel_std (int): The pixel std of the scale
      scale (float): The scale factor to transform the image
      rot (int): The rotate factor to transform the image
      num_joints_half_body (int): The joints threshold of the half body transform
      prob_half_body (float): The threshold of the half body transform
      flip (bool): Whether to flip the image
  Returns:
      records(dict): contain the image and coords after tranformed
class_docstr_tok: ["apply","data","augment","to","images","and","coords","to","achieve","the","flip",",","scale",",","rotate","and","half","body","transform","effect","for","training","image","Args",":","trainsize","(","list",")",":","[","w",",","h","]",",","Image","target","size","upper_body_ids","(","list",")",":","The","upper","body","joint","ids","flip_pairs","(","list",")",":","The","left-right","joints","exchange","order","list","pixel_std","(","int",")",":","The","pixel","std","of","the","scale","scale","(","float",")",":","The","scale","factor","to","transform","the","image","rot","(","int",")",":","The","rotate","factor","to","transform","the","image","num_joints_half_body","(","int",")",":","The","joints","threshold","of","the","half","body","transform","prob_half_body","(","float",")",":","The","threshold","of","the","half","body","transform","flip","(","bool",")",":","Whether","to","flip","the","image","Returns",":","records","(","dict",")",":","contain","the","image","and","coords","after","tranformed"]
code: def halfbody_transform(self, joints, joints_vis):
      upper_joints = []
      lower_joints = []
      for joint_id in range(joints.shape[0]):
          if joints_vis[joint_id][0] > 0:
              if joint_id in self.upper_body_ids:
                  upper_joints.append(joints[joint_id])
              else:
                  lower_joints.append(joints[joint_id])
      if np.random.randn() < 0.5 and len(upper_joints) > 2:
          selected_joints = upper_joints
      else:
          selected_joints = (
              lower_joints if len(lower_joints) > 2 else upper_joints
          )
      if len(selected_joints) < 2:
          return None, None
      selected_joints = np.array(selected_joints, dtype=np.float32)
      center = selected_joints.mean(axis=0)[:2]
      left_top = np.amin(selected_joints, axis=0)
      right_bottom = np.amax(selected_joints, axis=0)
      w = right_bottom[0] - left_top[0]
      h = right_bottom[1] - left_top[1]
      if w > self.aspect_ratio * h:
          h = w * 1.0 / self.aspect_ratio
      elif w < self.aspect_ratio * h:
          w = h * self.aspect_ratio
      scale = np.array(
          [w * 1.0 / self.pixel_std, h * 1.0 / self.pixel_std],
          dtype=np.float32,
      )
      scale = scale * 1.5
  
      return center, scale
  
imports: from __future__ import absolute_import
  import cv2
  import numpy
  import math
  import copy
  import random
  import uuid
  from numbers import Number, Integral
  from ...modeling.keypoint_utils import get_affine_mat_kernel, warp_affine_joints, get_affine_transform, affine_transform, get_warp_matrix
  from ppdet.core.workspace import serializable
  from ppdet.utils.logger import setup_logger
  import matplotlib.pyplot
  from PIL import Image, ImageDraw
  from mpl_toolkits.mplot3d import Axes3D
label_desc: Use image node_id 2 for calling the RandomFlipHalfBody3DTransformImages obj's underlying member method code with example usage: obj.halfbody_transform(joints, joints_vis) and returns: center,  scale, None,  None