|
|
|
|
| import numpy as np
|
| import cv2
|
|
|
|
|
|
|
|
|
| def bbox_from_detector(bbox, input_resolution=(224, 224), rescale=1.25):
|
| """
|
| Get center and scale of bounding box from bounding box.
|
| The expected format is [min_x, min_y, max_x, max_y].
|
| """
|
| CROP_IMG_HEIGHT, CROP_IMG_WIDTH = input_resolution
|
| CROP_ASPECT_RATIO = CROP_IMG_HEIGHT / float(CROP_IMG_WIDTH)
|
|
|
|
|
| center_x = (bbox[0] + bbox[2]) / 2.0
|
| center_y = (bbox[1] + bbox[3]) / 2.0
|
| center = np.array([center_x, center_y])
|
|
|
|
|
| bbox_w = bbox[2] - bbox[0]
|
| bbox_h = bbox[3] - bbox[1]
|
| bbox_size = max(bbox_w * CROP_ASPECT_RATIO, bbox_h)
|
|
|
| scale = np.array([bbox_size / CROP_ASPECT_RATIO, bbox_size]) / 200.0
|
|
|
|
|
| scale *= rescale
|
| return center, scale
|
|
|
| def get_transform(center, scale, res, rot=0):
|
| """Generate transformation matrix."""
|
|
|
| crop_aspect_ratio = res[0] / float(res[1])
|
| h = 200 * scale
|
| w = h / crop_aspect_ratio
|
| t = np.zeros((3, 3))
|
| t[0, 0] = float(res[1]) / w
|
| t[1, 1] = float(res[0]) / h
|
| t[0, 2] = res[1] * (-float(center[0]) / w + .5)
|
| t[1, 2] = res[0] * (-float(center[1]) / h + .5)
|
| t[2, 2] = 1
|
| if not rot == 0:
|
| rot = -rot
|
| rot_mat = np.zeros((3, 3))
|
| rot_rad = rot * np.pi / 180
|
| sn, cs = np.sin(rot_rad), np.cos(rot_rad)
|
| rot_mat[0, :2] = [cs, -sn]
|
| rot_mat[1, :2] = [sn, cs]
|
| rot_mat[2, 2] = 1
|
|
|
| t_mat = np.eye(3)
|
| t_mat[0, 2] = -res[1] / 2
|
| t_mat[1, 2] = -res[0] / 2
|
| t_inv = t_mat.copy()
|
| t_inv[:2, 2] *= -1
|
| t = np.dot(t_inv, np.dot(rot_mat, np.dot(t_mat, t)))
|
| return t
|
|
|
| def transform(pt, center, scale, res, invert=0, rot=0):
|
| """Transform pixel location to different reference."""
|
| t = get_transform(center, scale, res, rot=rot)
|
| if invert:
|
| t = np.linalg.inv(t)
|
| new_pt = np.array([pt[0] - 1, pt[1] - 1, 1.]).T
|
| new_pt = np.dot(t, new_pt)
|
| return np.array([round(new_pt[0]), round(new_pt[1])], dtype=int) + 1
|
|
|
| def crop(img, center, scale, res):
|
| """
|
| Crop image according to the supplied bounding box.
|
| res: [rows, cols]
|
| """
|
|
|
| ul = np.array(transform([1, 1], center, max(scale), res, invert=1)) - 1
|
|
|
| br = np.array(transform([res[1] + 1, res[0] + 1], center, max(scale), res, invert=1)) - 1
|
|
|
| new_shape = [br[1] - ul[1], br[0] - ul[0]]
|
| if len(img.shape) > 2:
|
| new_shape += [img.shape[2]]
|
| new_img = np.zeros(new_shape, dtype=np.float32)
|
|
|
|
|
| new_x = max(0, -ul[0]), min(br[0], len(img[0])) - ul[0]
|
| new_y = max(0, -ul[1]), min(br[1], len(img)) - ul[1]
|
|
|
| old_x = max(0, ul[0]), min(len(img[0]), br[0])
|
| old_y = max(0, ul[1]), min(len(img), br[1])
|
| try:
|
| new_img[new_y[0]:new_y[1], new_x[0]:new_x[1]] = img[old_y[0]:old_y[1], old_x[0]:old_x[1]]
|
| except Exception as e:
|
| print(e)
|
|
|
| new_img = cv2.resize(new_img, (res[1], res[0]))
|
| return new_img, new_shape, (old_x, old_y), (new_x, new_y)
|
|
|
|
|
| def split_kp2ds_for_aa(kp2ds, ret_face=False):
|
| kp2ds_body = (kp2ds[[0, 6, 6, 8, 10, 5, 7, 9, 12, 14, 16, 11, 13, 15, 2, 1, 4, 3, 17, 20]] + kp2ds[[0, 5, 6, 8, 10, 5, 7, 9, 12, 14, 16, 11, 13, 15, 2, 1, 4, 3, 18, 21]]) / 2
|
| kp2ds_lhand = kp2ds[91:112]
|
| kp2ds_rhand = kp2ds[112:133]
|
| kp2ds_face = kp2ds[22:91]
|
| if ret_face:
|
| return kp2ds_body.copy(), kp2ds_lhand.copy(), kp2ds_rhand.copy(), kp2ds_face.copy()
|
| return kp2ds_body.copy(), kp2ds_lhand.copy(), kp2ds_rhand.copy()
|
|
|
|
|
| def load_pose_metas_from_kp2ds_seq(kp2ds_seq, width, height):
|
| metas = []
|
| last_kp2ds_body = None
|
| for kps in kp2ds_seq:
|
| kps = kps.copy()
|
| kps[:, 0] /= width
|
| kps[:, 1] /= height
|
| kp2ds_body, kp2ds_lhand, kp2ds_rhand, kp2ds_face = split_kp2ds_for_aa(kps, ret_face=True)
|
|
|
|
|
| if last_kp2ds_body is not None and kp2ds_body[:, :2].min(axis=1).max() < 0:
|
| kp2ds_body = last_kp2ds_body
|
| last_kp2ds_body = kp2ds_body
|
|
|
| meta = {
|
| "width": width,
|
| "height": height,
|
| "keypoints_body": kp2ds_body,
|
| "keypoints_left_hand": kp2ds_lhand,
|
| "keypoints_right_hand": kp2ds_rhand,
|
| "keypoints_face": kp2ds_face,
|
| }
|
| metas.append(meta)
|
| return metas
|
|
|
| def aaposemeta_to_dwpose_scail(meta):
|
| """
|
| Convert AA pose metadata to DWpose format matching DWposeDetector output.
|
|
|
| DWpose format:
|
| - bodies: dict with 'candidate' (n, 24, 2) and 'subset' (n, 24) where subset contains indices
|
| - hands: array (2*n, 21, 2) - stacked right/left hands
|
| - faces: array (n, 68, 2)
|
| """
|
|
|
| candidate_body = meta['keypoints_body'][:-2][:, :2]
|
| score_body = meta['keypoints_body'][:-2][:, 2]
|
|
|
|
|
| subset_body = np.arange(len(candidate_body), dtype=float)
|
| subset_body[score_body <= 0.3] = -1
|
|
|
|
|
| bodies = {
|
| "candidate": np.expand_dims(candidate_body, axis=0),
|
| "subset": np.expand_dims(subset_body, axis=0)
|
| }
|
|
|
|
|
| hands_coords = np.stack([
|
| meta['keypoints_right_hand'][:, :2],
|
| meta['keypoints_left_hand'][:, :2]
|
| ], axis=0)
|
|
|
| hands_score = np.stack([
|
| meta['keypoints_right_hand'][:, 2],
|
| meta['keypoints_left_hand'][:, 2]
|
| ], axis=0)
|
|
|
|
|
| faces_coords = np.expand_dims(meta['keypoints_face'][1:][:, :2], axis=0)
|
| faces_score = np.expand_dims(meta['keypoints_face'][1:][:, 2], axis=0)
|
|
|
|
|
| dwpose_format = {
|
| "bodies": bodies,
|
| "hands": hands_coords,
|
| "faces": faces_coords
|
| }
|
|
|
|
|
| score_dict = {
|
| "body_score": np.expand_dims(score_body, axis=0),
|
| "hand_score": hands_score,
|
| "face_score": faces_score
|
| }
|
|
|
|
|
| dwpose_format.update(score_dict)
|
|
|
| return dwpose_format
|
|
|