import numpy as np import random def pose_offset(offset_x, offset_y, pose, vitposes): for i in range(len(pose["bodies"]["candidate"])): bodies = pose["bodies"] faces = pose["faces"][i] right_hand = pose["hands"][2 * i] left_hand = pose["hands"][2 * i + 1] candidate = bodies["candidate"][i] subset = bodies["subset"][i] for face_point in faces: if face_point[0] == -1 and face_point[1] == -1: continue face_point[0] = face_point[0] + offset_x face_point[1] = face_point[1] + offset_y for left_hand_point in left_hand: if left_hand_point[0] == -1 and left_hand_point[1] == -1: continue left_hand_point[0] = left_hand_point[0] + offset_x left_hand_point[1] = left_hand_point[1] + offset_y for right_hand_point in right_hand: if right_hand_point[0] == -1 and right_hand_point[1] == -1: continue right_hand_point[0] = right_hand_point[0] + offset_x right_hand_point[1] = right_hand_point[1] + offset_y assert len(candidate) == len(subset), f"candidate, length: {len(candidate)} and subset, length: {len(subset)} must have the same length" for idx, body_point in enumerate(candidate): if subset[idx] == -1: continue if body_point[0] == -1 and body_point[1] == -1: continue body_point[0] = body_point[0] + offset_x body_point[1] = body_point[1] + offset_y if vitposes is not None: for vitpose in vitposes: vitpose['keypoints_body'] = vitpose['keypoints_body'] + np.array([offset_x, offset_y, 0]) vitpose['keypoints_left_hand'] = vitpose['keypoints_left_hand'] + np.array([offset_x, offset_y, 0]) vitpose['keypoints_right_hand'] = vitpose['keypoints_right_hand'] + np.array([offset_x, offset_y, 0]) def pose_whole_scale(scale_x, scale_y, pose, vitposes): # 目前仅能用于单人 # 获取最左端的x 最右端的x 最上端的y 最下端的y min_x = float('inf') max_x = float('-inf') min_y = float('inf') max_y = float('-inf') if len(pose["bodies"]["candidate"]) > 1: return for i in range(len(pose["bodies"]["candidate"])): bodies = pose["bodies"] faces = pose["faces"][i] right_hand = pose["hands"][2 * i] left_hand = pose["hands"][2 * i + 1] candidate = bodies["candidate"][i] subset = bodies["subset"][i] for face_point in faces: if face_point[0] == -1 and face_point[1] == -1: continue min_x = min(min_x, face_point[0]) max_x = max(max_x, face_point[0]) min_y = min(min_y, face_point[1]) max_y = max(max_y, face_point[1]) for left_hand_point in left_hand: if left_hand_point[0] == -1 and left_hand_point[1] == -1: continue min_x = min(min_x, left_hand_point[0]) max_x = max(max_x, left_hand_point[0]) min_y = min(min_y, left_hand_point[1]) max_y = max(max_y, left_hand_point[1]) for right_hand_point in right_hand: if right_hand_point[0] == -1 and right_hand_point[1] == -1: continue min_x = min(min_x, right_hand_point[0]) max_x = max(max_x, right_hand_point[0]) min_y = min(min_y, right_hand_point[1]) max_y = max(max_y, right_hand_point[1]) assert len(candidate) == len(subset), "candidate and subset must have the same length" for idx, body_point in enumerate(candidate): if subset[idx] == -1: continue if body_point[0] == -1 and body_point[1] == -1: continue min_x = min(min_x, body_point[0]) max_x = max(max_x, body_point[0]) min_y = min(min_y, body_point[1]) max_y = max(max_y, body_point[1]) # 计算缩放比例 # 根据bbox中心进行dilate, 倍数为x_scale, y_scale bbox_center_x = (min_x + max_x) / 2 bbox_center_y = (min_y + max_y) / 2 for i in range(len(pose["bodies"]["candidate"])): bodies = pose["bodies"] candidate = bodies["candidate"][i] for body_point in candidate: if body_point[0] == -1 and body_point[1] == -1: continue body_point[0] = body_point[0] + (body_point[0] - bbox_center_x) * scale_x # scale越大,越远离中心,变化越大 body_point[1] = body_point[1] + (body_point[1] - bbox_center_y) * scale_y for face_point in faces: if face_point[0] == -1 and face_point[1] == -1: continue face_point[0] = face_point[0] + (face_point[0] - bbox_center_x) * scale_x face_point[1] = face_point[1] + (face_point[1] - bbox_center_y) * scale_y for left_hand_point in left_hand: if left_hand_point[0] == -1 and left_hand_point[1] == -1: continue left_hand_point[0] = left_hand_point[0] + (left_hand_point[0] - bbox_center_x) * scale_x left_hand_point[1] = left_hand_point[1] + (left_hand_point[1] - bbox_center_y) * scale_y for right_hand_point in right_hand: if right_hand_point[0] == -1 and right_hand_point[1] == -1: continue right_hand_point[0] = right_hand_point[0] + (right_hand_point[0] - bbox_center_x) * scale_x right_hand_point[1] = right_hand_point[1] + (right_hand_point[1] - bbox_center_y) * scale_y if vitposes is not None: min_x = float('inf') max_x = float('-inf') min_y = float('inf') max_y = float('-inf') if len(vitposes) > 1: return for vitpose in vitposes: for body_point in vitpose['keypoints_body']: if body_point[2] < 0.4: continue min_x = min(min_x, body_point[0]) max_x = max(max_x, body_point[0]) min_y = min(min_y, body_point[1]) max_y = max(max_y, body_point[1]) for left_hand_point in vitpose['keypoints_left_hand']: if left_hand_point[2] < 0.4: continue min_x = min(min_x, left_hand_point[0]) max_x = max(max_x, left_hand_point[0]) min_y = min(min_y, left_hand_point[1]) max_y = max(max_y, left_hand_point[1]) for right_hand_point in vitpose['keypoints_right_hand']: if right_hand_point[2] < 0.4: continue min_x = min(min_x, right_hand_point[0]) max_x = max(max_x, right_hand_point[0]) min_y = min(min_y, right_hand_point[1]) max_y = max(max_y, right_hand_point[1]) bbox_center_x = (min_x + max_x) / 2 bbox_center_y = (min_y + max_y) / 2 for body_point in vitpose['keypoints_body']: body_point[0] = body_point[0] + (body_point[0] - bbox_center_x) * scale_x body_point[1] = body_point[1] + (body_point[1] - bbox_center_y) * scale_y for left_hand_point in vitpose['keypoints_left_hand']: left_hand_point[0] = left_hand_point[0] + (left_hand_point[0] - bbox_center_x) * scale_x left_hand_point[1] = left_hand_point[1] + (left_hand_point[1] - bbox_center_y) * scale_y for right_hand_point in vitpose['keypoints_right_hand']: right_hand_point[0] = right_hand_point[0] + (right_hand_point[0] - bbox_center_x) * scale_x right_hand_point[1] = right_hand_point[1] + (right_hand_point[1] - bbox_center_y) * scale_y # 如果做多人增强,需要修改逻辑,每个人都有随机性,现在都是做单人增强,增强方法一致 def pose_reshape(alpha, pose, vitposes, anchor_point, anchor_part, end_point, end_part, affected_body_points, affected_faces_points, affected_left_hands_points, affected_right_hands_points): """ 直接修改原始pose中的某些点的位置,通过根据一个不动点和端点之间的向量偏移被影响点的位置。 一次只能有一个anchor_point, 一个end_point,多个affected_points alpha: 变化比例 anchor_point: 起始点 anchor_part: 起始点所属的身体部分,0代表body candidate, 1代表face, 2代表hand end_point: 中止点 end_part: 中止点所属的身体部分,0代表body candidate, 1代表face, 2代表hand """ for i in range(len(pose["bodies"]["candidate"])): bodies = pose["bodies"] # faces = pose["faces"][i:i+1] faces = pose["faces"][i] # hands = pose["hands"][2*i:2*i+2] right_hand = pose["hands"][2 * i] left_hand = pose["hands"][2 * i + 1] candidate = bodies["candidate"][i] # subset = bodies["subset"][i:i+1] subset = bodies["subset"][i] assert anchor_part == 0, "anchor part must belong to the body" anchor_x, anchor_y = candidate[anchor_point] if subset[anchor_point] == -1: continue if end_part == 0: end_x, end_y = candidate[end_point] if subset[end_point] == -1: continue elif end_part == 1: end_x, end_y = faces[end_point] # 不考虑Hands if end_x == -1 and end_y == -1: continue vector_x = end_x - anchor_x vector_y = end_y - anchor_y offset_x = vector_x * alpha offset_y = vector_y * alpha for affected_body_point in affected_body_points: if subset[affected_body_point] == -1: continue affected_x, affected_y = candidate[affected_body_point] candidate[affected_body_point] = [affected_x + offset_x, affected_y + offset_y] for affected_faces_point in affected_faces_points: affected_x, affected_y = faces[affected_faces_point] if affected_x == -1 and affected_y == -1: continue faces[affected_faces_point] = [affected_x + offset_x, affected_y + offset_y] for affected_hands_point in affected_left_hands_points: affected_x, affected_y = left_hand[affected_hands_point] if affected_x == -1 and affected_y == -1: continue left_hand[affected_hands_point] = [affected_x + offset_x, affected_y + offset_y] for affected_hands_point in affected_right_hands_points: affected_x, affected_y = right_hand[affected_hands_point] if affected_x == -1 and affected_y == -1: continue right_hand[affected_hands_point] = [affected_x + offset_x, affected_y + offset_y] if vitposes is not None: vit_visible_threshold = 0.5 for vitpose in vitposes: assert anchor_part == 0, "anchor part must belong to the body" anchor_x, anchor_y, _ = vitpose['keypoints_body'][anchor_point] if vitpose['keypoints_body'][anchor_point][2] < vit_visible_threshold: continue if end_part == 0: end_x, end_y, _ = vitpose['keypoints_body'][end_point] if vitpose['keypoints_body'][end_point][2] < vit_visible_threshold: continue # 不考虑hands elif end_part == 1: continue # ViTPose的脸不动 vector_x = end_x - anchor_x vector_y = end_y - anchor_y offset_x = vector_x * alpha offset_y = vector_y * alpha for affected_body_point in affected_body_points: if vitpose['keypoints_body'][affected_body_point][2] < vit_visible_threshold: continue vitpose['keypoints_body'][affected_body_point][0] = vitpose['keypoints_body'][affected_body_point][0] + offset_x vitpose['keypoints_body'][affected_body_point][1] = vitpose['keypoints_body'][affected_body_point][1] + offset_y # 左右标记相反,需要互换 for affected_left_hand_point in affected_left_hands_points: if vitpose['keypoints_right_hand'][affected_left_hand_point][2] < vit_visible_threshold: continue vitpose['keypoints_right_hand'][affected_left_hand_point][0] = vitpose['keypoints_right_hand'][affected_left_hand_point][0] + offset_x vitpose['keypoints_right_hand'][affected_left_hand_point][1] = vitpose['keypoints_right_hand'][affected_left_hand_point][1] + offset_y for affected_right_hand_point in affected_right_hands_points: if vitpose['keypoints_left_hand'][affected_right_hand_point][2] < vit_visible_threshold: continue vitpose['keypoints_left_hand'][affected_right_hand_point][0] = vitpose['keypoints_left_hand'][affected_right_hand_point][0] + offset_x vitpose['keypoints_left_hand'][affected_right_hand_point][1] = vitpose['keypoints_left_hand'][affected_right_hand_point][1] + offset_y # reshapePool只负责形变,骨骼偏移、丢弃等得从draw层来做 class reshapePool: def __init__(self, alpha): # 对每个视频只初始化一次 self.faces_indices = np.arange(0, 68) self.left_hands_indices = np.arange(0, 21) self.right_hands_indices = np.arange(0, 21) self.alpha = alpha # 0.1 self.offset_x = random.uniform(-1/16, 1/16) self.offset_y = random.uniform(-1/16, 1/16) self.scale_x = random.uniform(-alpha/2, alpha/2) self.scale_y = random.uniform(-alpha/2, alpha/2) self.body_reshape_methods = [ self.extend_body, self.extend_arm, self.extend_leg, self.shrink_body, self.shrink_arm, self.shrink_leg, ] self.scale_reshape_methods = [ self.offset_wholebody, # self.scale_wholebody, self.dilate_face, self.shrink_face, ] self.selected_methods = random.sample(self.body_reshape_methods, 2) + random.sample(self.scale_reshape_methods, random.choice([0, 1])) def apply_random_reshapes(self, pose, vitposes=None): # Apply the two selected reshape methods for method in self.selected_methods: method(pose, vitposes) def offset_wholebody(self, pose, vitposes): pose_offset(self.offset_x, self.offset_y, pose, vitposes) def scale_wholebody(self, pose, vitposes): pose_whole_scale(self.scale_x, self.scale_y, pose, vitposes) def extend_body(self, pose, vitposes): pose_reshape(self.alpha, pose, vitposes, 1, 0, 8, 0, [8, 9, 10], [], [], [] ) pose_reshape(self.alpha, pose, vitposes, 1, 0, 11, 0, [11, 12, 13], [], [], [] ) def shrink_body(self, pose, vitposes): pose_reshape(-self.alpha, pose, vitposes, 1, 0, 8, 0, [8, 9, 10], [], [], [] ) pose_reshape(-self.alpha, pose, vitposes, 1, 0, 11, 0, [11, 12, 13], [], [], [] ) def extend_arm(self, pose, vitposes): pose_reshape(self.alpha, pose, vitposes, 2, 0, 3, 0, [3, 4], [], self.left_hands_indices, [] ) pose_reshape(self.alpha, pose, vitposes, 5, 0, 6, 0, [6, 7], [], [], self.right_hands_indices ) pose_reshape(self.alpha, pose, vitposes, 3, 0, 4, 0, [4], [], self.left_hands_indices, [] ) pose_reshape(self.alpha, pose, vitposes, 6, 0, 7, 0, [7], [], [], self.right_hands_indices ) def shrink_arm(self, pose, vitposes): pose_reshape(-self.alpha, pose, vitposes, 2, 0, 3, 0, [3, 4], [], self.left_hands_indices, [] ) pose_reshape(-self.alpha, pose, vitposes, 5, 0, 6, 0, [6, 7], [], [], self.right_hands_indices ) pose_reshape(-self.alpha, pose, vitposes, 3, 0, 4, 0, [4], [], self.left_hands_indices, [] ) pose_reshape(-self.alpha, pose, vitposes, 6, 0, 7, 0, [7], [], [], self.right_hands_indices ) def extend_leg(self, pose, vitposes): pose_reshape(self.alpha, pose, vitposes, 8, 0, 9, 0, [9, 10], [], [], [] ) pose_reshape(self.alpha, pose, vitposes, 11, 0, 12, 0, [12, 13], [], [], [] ) pose_reshape(self.alpha, pose, vitposes, 9, 0, 10, 0, [10], [], [], [] ) pose_reshape(self.alpha, pose, vitposes, 12, 0, 13, 0, [13], [], [], [] ) def shrink_leg(self, pose, vitposes): pose_reshape(-self.alpha, pose, vitposes, 8, 0, 9, 0, [9, 10], [], [], [] ) pose_reshape(-self.alpha, pose, vitposes, 11, 0, 12, 0, [12, 13], [], [], [] ) pose_reshape(-self.alpha, pose, vitposes, 9, 0, 10, 0, [10], [], [], [] ) pose_reshape(-self.alpha, pose, vitposes, 12, 0, 13, 0, [13], [], [], [] ) def extend_shoulder(self, pose, vitposes): pose_reshape(self.alpha, pose, vitposes, 1, 0, 2, 0, [2, 3, 4], [], self.left_hands_indices, [] ) pose_reshape(self.alpha, pose, vitposes, 1, 0, 5, 0, [5, 6, 7], [], [], self.right_hands_indices ) def shrink_shoulder(self, pose, vitposes): pose_reshape(-self.alpha, pose, vitposes, 1, 0, 2, 0, [2, 3, 4], [], self.left_hands_indices, [] ) pose_reshape(-self.alpha, pose, vitposes, 1, 0, 5, 0, [5, 6, 7], [], [], self.right_hands_indices ) def dilate_face(self, pose, vitposes): for i in self.faces_indices: pose_reshape(self.alpha, pose, vitposes, 0, 0, i, 1, [], [i], [], [] ) for i in [14, 15, 16, 17]: pose_reshape(self.alpha, pose, vitposes, 0, 0, i, 0, [i], [], [], [] ) def shrink_face(self, pose, vitposes): # 缩小脸会看不清 for i in self.faces_indices: pose_reshape(-self.alpha / 2, pose, vitposes, 0, 0, i, 1, [], [i], [], [] ) for i in [14, 15, 16, 17]: pose_reshape(-self.alpha / 2, pose, vitposes, 0, 0, i, 0, [i], [], [], [] )