|
|
|
|
|
import os |
|
|
import cv2 |
|
|
import time |
|
|
import math |
|
|
import matplotlib |
|
|
import matplotlib.pyplot as plt |
|
|
import numpy as np |
|
|
from typing import Dict, List |
|
|
import random |
|
|
from pose2d_utils import AAPoseMeta |
|
|
|
|
|
|
|
|
def draw_handpose(canvas, keypoints, hand_score_th=0.6): |
|
|
""" |
|
|
Draw keypoints and connections representing hand pose on a given canvas. |
|
|
|
|
|
Args: |
|
|
canvas (np.ndarray): A 3D numpy array representing the canvas (image) on which to draw the hand pose. |
|
|
keypoints (List[Keypoint]| None): A list of Keypoint objects representing the hand keypoints to be drawn |
|
|
or None if no keypoints are present. |
|
|
|
|
|
Returns: |
|
|
np.ndarray: A 3D numpy array representing the modified canvas with the drawn hand pose. |
|
|
|
|
|
Note: |
|
|
The function expects the x and y coordinates of the keypoints to be normalized between 0 and 1. |
|
|
""" |
|
|
eps = 0.01 |
|
|
|
|
|
H, W, C = canvas.shape |
|
|
stickwidth = max(int(min(H, W) / 200), 1) |
|
|
|
|
|
edges = [ |
|
|
[0, 1], |
|
|
[1, 2], |
|
|
[2, 3], |
|
|
[3, 4], |
|
|
[0, 5], |
|
|
[5, 6], |
|
|
[6, 7], |
|
|
[7, 8], |
|
|
[0, 9], |
|
|
[9, 10], |
|
|
[10, 11], |
|
|
[11, 12], |
|
|
[0, 13], |
|
|
[13, 14], |
|
|
[14, 15], |
|
|
[15, 16], |
|
|
[0, 17], |
|
|
[17, 18], |
|
|
[18, 19], |
|
|
[19, 20], |
|
|
] |
|
|
|
|
|
for ie, (e1, e2) in enumerate(edges): |
|
|
k1 = keypoints[e1] |
|
|
k2 = keypoints[e2] |
|
|
if k1 is None or k2 is None: |
|
|
continue |
|
|
if k1[2] < hand_score_th or k2[2] < hand_score_th: |
|
|
continue |
|
|
|
|
|
x1 = int(k1[0]) |
|
|
y1 = int(k1[1]) |
|
|
x2 = int(k2[0]) |
|
|
y2 = int(k2[1]) |
|
|
if x1 > eps and y1 > eps and x2 > eps and y2 > eps: |
|
|
cv2.line( |
|
|
canvas, |
|
|
(x1, y1), |
|
|
(x2, y2), |
|
|
matplotlib.colors.hsv_to_rgb([ie / float(len(edges)), 1.0, 1.0]) * 255, |
|
|
thickness=stickwidth, |
|
|
) |
|
|
|
|
|
for keypoint in keypoints: |
|
|
|
|
|
if keypoint is None: |
|
|
continue |
|
|
if keypoint[2] < hand_score_th: |
|
|
continue |
|
|
|
|
|
x, y = keypoint[0], keypoint[1] |
|
|
x = int(x) |
|
|
y = int(y) |
|
|
if x > eps and y > eps: |
|
|
cv2.circle(canvas, (x, y), stickwidth, (0, 0, 255), thickness=-1) |
|
|
return canvas |
|
|
|
|
|
|
|
|
def draw_handpose_new(canvas, keypoints, stickwidth_type='v2', hand_score_th=0.6): |
|
|
""" |
|
|
Draw keypoints and connections representing hand pose on a given canvas. |
|
|
|
|
|
Args: |
|
|
canvas (np.ndarray): A 3D numpy array representing the canvas (image) on which to draw the hand pose. |
|
|
keypoints (List[Keypoint]| None): A list of Keypoint objects representing the hand keypoints to be drawn |
|
|
or None if no keypoints are present. |
|
|
|
|
|
Returns: |
|
|
np.ndarray: A 3D numpy array representing the modified canvas with the drawn hand pose. |
|
|
|
|
|
Note: |
|
|
The function expects the x and y coordinates of the keypoints to be normalized between 0 and 1. |
|
|
""" |
|
|
eps = 0.01 |
|
|
|
|
|
H, W, C = canvas.shape |
|
|
if stickwidth_type == 'v1': |
|
|
stickwidth = max(int(min(H, W) / 200), 1) |
|
|
elif stickwidth_type == 'v2': |
|
|
stickwidth = max(max(int(min(H, W) / 200) - 1, 1) // 2, 1) |
|
|
|
|
|
edges = [ |
|
|
[0, 1], |
|
|
[1, 2], |
|
|
[2, 3], |
|
|
[3, 4], |
|
|
[0, 5], |
|
|
[5, 6], |
|
|
[6, 7], |
|
|
[7, 8], |
|
|
[0, 9], |
|
|
[9, 10], |
|
|
[10, 11], |
|
|
[11, 12], |
|
|
[0, 13], |
|
|
[13, 14], |
|
|
[14, 15], |
|
|
[15, 16], |
|
|
[0, 17], |
|
|
[17, 18], |
|
|
[18, 19], |
|
|
[19, 20], |
|
|
] |
|
|
|
|
|
for ie, (e1, e2) in enumerate(edges): |
|
|
k1 = keypoints[e1] |
|
|
k2 = keypoints[e2] |
|
|
if k1 is None or k2 is None: |
|
|
continue |
|
|
if k1[2] < hand_score_th or k2[2] < hand_score_th: |
|
|
continue |
|
|
|
|
|
x1 = int(k1[0]) |
|
|
y1 = int(k1[1]) |
|
|
x2 = int(k2[0]) |
|
|
y2 = int(k2[1]) |
|
|
if x1 > eps and y1 > eps and x2 > eps and y2 > eps: |
|
|
cv2.line( |
|
|
canvas, |
|
|
(x1, y1), |
|
|
(x2, y2), |
|
|
matplotlib.colors.hsv_to_rgb([ie / float(len(edges)), 1.0, 1.0]) * 255, |
|
|
thickness=stickwidth, |
|
|
) |
|
|
|
|
|
for keypoint in keypoints: |
|
|
|
|
|
if keypoint is None: |
|
|
continue |
|
|
if keypoint[2] < hand_score_th: |
|
|
continue |
|
|
|
|
|
x, y = keypoint[0], keypoint[1] |
|
|
x = int(x) |
|
|
y = int(y) |
|
|
if x > eps and y > eps: |
|
|
cv2.circle(canvas, (x, y), stickwidth, (0, 0, 255), thickness=-1) |
|
|
return canvas |
|
|
|
|
|
|
|
|
def draw_ellipse_by_2kp(img, keypoint1, keypoint2, color, threshold=0.6): |
|
|
H, W, C = img.shape |
|
|
stickwidth = max(int(min(H, W) / 200), 1) |
|
|
|
|
|
if keypoint1[-1] < threshold or keypoint2[-1] < threshold: |
|
|
return img |
|
|
|
|
|
Y = np.array([keypoint1[0], keypoint2[0]]) |
|
|
X = np.array([keypoint1[1], keypoint2[1]]) |
|
|
mX = np.mean(X) |
|
|
mY = np.mean(Y) |
|
|
length = ((X[0] - X[1]) ** 2 + (Y[0] - Y[1]) ** 2) ** 0.5 |
|
|
angle = math.degrees(math.atan2(X[0] - X[1], Y[0] - Y[1])) |
|
|
polygon = cv2.ellipse2Poly((int(mY), int(mX)), (int(length / 2), stickwidth), int(angle), 0, 360, 1) |
|
|
cv2.fillConvexPoly(img, polygon, [int(float(c) * 0.6) for c in color]) |
|
|
return img |
|
|
|
|
|
|
|
|
def split_pose2d_kps_to_aa(kp2ds: np.ndarray) -> List[np.ndarray]: |
|
|
"""Convert the 133 keypoints from pose2d to body and hands keypoints. |
|
|
|
|
|
Args: |
|
|
kp2ds (np.ndarray): [133, 2] |
|
|
|
|
|
Returns: |
|
|
List[np.ndarray]: _description_ |
|
|
""" |
|
|
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] |
|
|
return kp2ds_body.copy(), kp2ds_lhand.copy(), kp2ds_rhand.copy() |
|
|
|
|
|
|
|
|
def draw_aapose_by_meta(img, meta: AAPoseMeta, threshold=0.5, stick_width_norm=200, draw_hand=True, draw_head=True): |
|
|
kp2ds = np.concatenate([meta.kps_body, meta.kps_body_p[:, None]], axis=1) |
|
|
kp2ds_lhand = np.concatenate([meta.kps_lhand, meta.kps_lhand_p[:, None]], axis=1) |
|
|
kp2ds_rhand = np.concatenate([meta.kps_rhand, meta.kps_rhand_p[:, None]], axis=1) |
|
|
pose_img = draw_aapose(img, kp2ds, threshold, kp2ds_lhand=kp2ds_lhand, kp2ds_rhand=kp2ds_rhand, stick_width_norm=stick_width_norm, draw_hand=draw_hand, draw_head=draw_head) |
|
|
return pose_img |
|
|
|
|
|
def draw_aapose_by_meta_new(img, meta: AAPoseMeta, threshold=0.5, stickwidth_type='v2', draw_hand=True, draw_head=True): |
|
|
kp2ds = np.concatenate([meta.kps_body, meta.kps_body_p[:, None]], axis=1) |
|
|
kp2ds_lhand = np.concatenate([meta.kps_lhand, meta.kps_lhand_p[:, None]], axis=1) |
|
|
kp2ds_rhand = np.concatenate([meta.kps_rhand, meta.kps_rhand_p[:, None]], axis=1) |
|
|
pose_img = draw_aapose_new(img, kp2ds, threshold, kp2ds_lhand=kp2ds_lhand, kp2ds_rhand=kp2ds_rhand, |
|
|
stickwidth_type=stickwidth_type, draw_hand=draw_hand, draw_head=draw_head) |
|
|
return pose_img |
|
|
|
|
|
def draw_hand_by_meta(img, meta: AAPoseMeta, threshold=0.5, stick_width_norm=200): |
|
|
kp2ds = np.concatenate([meta.kps_body, meta.kps_body_p[:, None] * 0], axis=1) |
|
|
kp2ds_lhand = np.concatenate([meta.kps_lhand, meta.kps_lhand_p[:, None]], axis=1) |
|
|
kp2ds_rhand = np.concatenate([meta.kps_rhand, meta.kps_rhand_p[:, None]], axis=1) |
|
|
pose_img = draw_aapose(img, kp2ds, threshold, kp2ds_lhand=kp2ds_lhand, kp2ds_rhand=kp2ds_rhand, stick_width_norm=stick_width_norm, draw_hand=True, draw_head=False) |
|
|
return pose_img |
|
|
|
|
|
|
|
|
def draw_aaface_by_meta(img, meta: AAPoseMeta, threshold=0.5, stick_width_norm=200, draw_hand=False, draw_head=True): |
|
|
kp2ds = np.concatenate([meta.kps_body, meta.kps_body_p[:, None]], axis=1) |
|
|
|
|
|
|
|
|
pose_img = draw_M(img, kp2ds, threshold, kp2ds_lhand=None, kp2ds_rhand=None, stick_width_norm=stick_width_norm, draw_hand=draw_hand, draw_head=draw_head) |
|
|
return pose_img |
|
|
|
|
|
|
|
|
def draw_aanose_by_meta(img, meta: AAPoseMeta, threshold=0.5, stick_width_norm=100, draw_hand=False): |
|
|
kp2ds = np.concatenate([meta.kps_body, meta.kps_body_p[:, None]], axis=1) |
|
|
|
|
|
|
|
|
pose_img = draw_nose(img, kp2ds, threshold, kp2ds_lhand=None, kp2ds_rhand=None, stick_width_norm=stick_width_norm, draw_hand=draw_hand) |
|
|
return pose_img |
|
|
|
|
|
|
|
|
def gen_face_motion_seq(img, metas: List[AAPoseMeta], threshold=0.5, stick_width_norm=200): |
|
|
|
|
|
return |
|
|
|
|
|
|
|
|
def draw_M( |
|
|
img, |
|
|
kp2ds, |
|
|
threshold=0.6, |
|
|
data_to_json=None, |
|
|
idx=-1, |
|
|
kp2ds_lhand=None, |
|
|
kp2ds_rhand=None, |
|
|
draw_hand=False, |
|
|
stick_width_norm=200, |
|
|
draw_head=True |
|
|
): |
|
|
""" |
|
|
Draw keypoints and connections representing hand pose on a given canvas. |
|
|
|
|
|
Args: |
|
|
canvas (np.ndarray): A 3D numpy array representing the canvas (image) on which to draw the hand pose. |
|
|
keypoints (List[Keypoint]| None): A list of Keypoint objects representing the hand keypoints to be drawn |
|
|
or None if no keypoints are present. |
|
|
|
|
|
Returns: |
|
|
np.ndarray: A 3D numpy array representing the modified canvas with the drawn hand pose. |
|
|
|
|
|
Note: |
|
|
The function expects the x and y coordinates of the keypoints to be normalized between 0 and 1. |
|
|
""" |
|
|
|
|
|
new_kep_list = [ |
|
|
"Nose", |
|
|
"Neck", |
|
|
"RShoulder", |
|
|
"RElbow", |
|
|
"RWrist", |
|
|
"LShoulder", |
|
|
"LElbow", |
|
|
"LWrist", |
|
|
"RHip", |
|
|
"RKnee", |
|
|
"RAnkle", |
|
|
"LHip", |
|
|
"LKnee", |
|
|
"LAnkle", |
|
|
"REye", |
|
|
"LEye", |
|
|
"REar", |
|
|
"LEar", |
|
|
"LToe", |
|
|
"RToe", |
|
|
] |
|
|
|
|
|
|
|
|
kp2ds = kp2ds.copy() |
|
|
|
|
|
kp2ds[[1,2,3,4,5,6,7,8,9,10,11,12,13,18,19], 2] = 0 |
|
|
if not draw_head: |
|
|
kp2ds[[0,14,15,16,17], 2] = 0 |
|
|
kp2ds_body = kp2ds |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
limbSeq = [ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[1, 15], |
|
|
[15, 17], |
|
|
[1, 16], |
|
|
[16, 18], |
|
|
|
|
|
|
|
|
] |
|
|
|
|
|
colors = [ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[170, 0, 255], |
|
|
[255, 0, 255], |
|
|
[255, 0, 170], |
|
|
[255, 0, 85], |
|
|
|
|
|
|
|
|
|
|
|
] |
|
|
|
|
|
H, W, C = img.shape |
|
|
stickwidth = max(int(min(H, W) / stick_width_norm), 1) |
|
|
|
|
|
for _idx, ((k1_index, k2_index), color) in enumerate(zip(limbSeq, colors)): |
|
|
keypoint1 = kp2ds_body[k1_index - 1] |
|
|
keypoint2 = kp2ds_body[k2_index - 1] |
|
|
|
|
|
if keypoint1[-1] < threshold or keypoint2[-1] < threshold: |
|
|
continue |
|
|
|
|
|
Y = np.array([keypoint1[0], keypoint2[0]]) |
|
|
X = np.array([keypoint1[1], keypoint2[1]]) |
|
|
mX = np.mean(X) |
|
|
mY = np.mean(Y) |
|
|
length = ((X[0] - X[1]) ** 2 + (Y[0] - Y[1]) ** 2) ** 0.5 |
|
|
angle = math.degrees(math.atan2(X[0] - X[1], Y[0] - Y[1])) |
|
|
polygon = cv2.ellipse2Poly((int(mY), int(mX)), (int(length / 2), stickwidth), int(angle), 0, 360, 1) |
|
|
cv2.fillConvexPoly(img, polygon, [int(float(c) * 0.6) for c in color]) |
|
|
|
|
|
for _idx, (keypoint, color) in enumerate(zip(kp2ds_body, colors)): |
|
|
if keypoint[-1] < threshold: |
|
|
continue |
|
|
x, y = keypoint[0], keypoint[1] |
|
|
|
|
|
cv2.circle(img, (int(x), int(y)), stickwidth, color, thickness=-1) |
|
|
|
|
|
if draw_hand: |
|
|
img = draw_handpose(img, kp2ds_lhand, hand_score_th=threshold) |
|
|
img = draw_handpose(img, kp2ds_rhand, hand_score_th=threshold) |
|
|
|
|
|
kp2ds_body[:, 0] /= W |
|
|
kp2ds_body[:, 1] /= H |
|
|
|
|
|
if data_to_json is not None: |
|
|
if idx == -1: |
|
|
data_to_json.append( |
|
|
{ |
|
|
"image_id": "frame_{:05d}.jpg".format(len(data_to_json) + 1), |
|
|
"height": H, |
|
|
"width": W, |
|
|
"category_id": 1, |
|
|
"keypoints_body": kp2ds_body.tolist(), |
|
|
"keypoints_left_hand": kp2ds_lhand.tolist(), |
|
|
"keypoints_right_hand": kp2ds_rhand.tolist(), |
|
|
} |
|
|
) |
|
|
else: |
|
|
data_to_json[idx] = { |
|
|
"image_id": "frame_{:05d}.jpg".format(idx + 1), |
|
|
"height": H, |
|
|
"width": W, |
|
|
"category_id": 1, |
|
|
"keypoints_body": kp2ds_body.tolist(), |
|
|
"keypoints_left_hand": kp2ds_lhand.tolist(), |
|
|
"keypoints_right_hand": kp2ds_rhand.tolist(), |
|
|
} |
|
|
return img |
|
|
|
|
|
|
|
|
def draw_nose( |
|
|
img, |
|
|
kp2ds, |
|
|
threshold=0.6, |
|
|
data_to_json=None, |
|
|
idx=-1, |
|
|
kp2ds_lhand=None, |
|
|
kp2ds_rhand=None, |
|
|
draw_hand=False, |
|
|
stick_width_norm=200, |
|
|
): |
|
|
""" |
|
|
Draw keypoints and connections representing hand pose on a given canvas. |
|
|
|
|
|
Args: |
|
|
canvas (np.ndarray): A 3D numpy array representing the canvas (image) on which to draw the hand pose. |
|
|
keypoints (List[Keypoint]| None): A list of Keypoint objects representing the hand keypoints to be drawn |
|
|
or None if no keypoints are present. |
|
|
|
|
|
Returns: |
|
|
np.ndarray: A 3D numpy array representing the modified canvas with the drawn hand pose. |
|
|
|
|
|
Note: |
|
|
The function expects the x and y coordinates of the keypoints to be normalized between 0 and 1. |
|
|
""" |
|
|
|
|
|
new_kep_list = [ |
|
|
"Nose", |
|
|
"Neck", |
|
|
"RShoulder", |
|
|
"RElbow", |
|
|
"RWrist", |
|
|
"LShoulder", |
|
|
"LElbow", |
|
|
"LWrist", |
|
|
"RHip", |
|
|
"RKnee", |
|
|
"RAnkle", |
|
|
"LHip", |
|
|
"LKnee", |
|
|
"LAnkle", |
|
|
"REye", |
|
|
"LEye", |
|
|
"REar", |
|
|
"LEar", |
|
|
"LToe", |
|
|
"RToe", |
|
|
] |
|
|
|
|
|
|
|
|
kp2ds = kp2ds.copy() |
|
|
kp2ds[1:, 2] = 0 |
|
|
|
|
|
kp2ds_body = kp2ds |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
limbSeq = [ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[1, 15], |
|
|
[15, 17], |
|
|
[1, 16], |
|
|
[16, 18], |
|
|
|
|
|
|
|
|
] |
|
|
|
|
|
colors = [ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[170, 0, 255], |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
] |
|
|
|
|
|
H, W, C = img.shape |
|
|
stickwidth = max(int(min(H, W) / stick_width_norm), 1) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for _idx, (keypoint, color) in enumerate(zip(kp2ds_body, colors)): |
|
|
if keypoint[-1] < threshold: |
|
|
continue |
|
|
x, y = keypoint[0], keypoint[1] |
|
|
|
|
|
cv2.circle(img, (int(x), int(y)), stickwidth, color, thickness=-1) |
|
|
|
|
|
if draw_hand: |
|
|
img = draw_handpose(img, kp2ds_lhand, hand_score_th=threshold) |
|
|
img = draw_handpose(img, kp2ds_rhand, hand_score_th=threshold) |
|
|
|
|
|
kp2ds_body[:, 0] /= W |
|
|
kp2ds_body[:, 1] /= H |
|
|
|
|
|
if data_to_json is not None: |
|
|
if idx == -1: |
|
|
data_to_json.append( |
|
|
{ |
|
|
"image_id": "frame_{:05d}.jpg".format(len(data_to_json) + 1), |
|
|
"height": H, |
|
|
"width": W, |
|
|
"category_id": 1, |
|
|
"keypoints_body": kp2ds_body.tolist(), |
|
|
"keypoints_left_hand": kp2ds_lhand.tolist(), |
|
|
"keypoints_right_hand": kp2ds_rhand.tolist(), |
|
|
} |
|
|
) |
|
|
else: |
|
|
data_to_json[idx] = { |
|
|
"image_id": "frame_{:05d}.jpg".format(idx + 1), |
|
|
"height": H, |
|
|
"width": W, |
|
|
"category_id": 1, |
|
|
"keypoints_body": kp2ds_body.tolist(), |
|
|
"keypoints_left_hand": kp2ds_lhand.tolist(), |
|
|
"keypoints_right_hand": kp2ds_rhand.tolist(), |
|
|
} |
|
|
return img |
|
|
|
|
|
|
|
|
def draw_aapose( |
|
|
img, |
|
|
kp2ds, |
|
|
threshold=0.6, |
|
|
data_to_json=None, |
|
|
idx=-1, |
|
|
kp2ds_lhand=None, |
|
|
kp2ds_rhand=None, |
|
|
draw_hand=False, |
|
|
stick_width_norm=200, |
|
|
draw_head=True |
|
|
): |
|
|
""" |
|
|
Draw keypoints and connections representing hand pose on a given canvas. |
|
|
|
|
|
Args: |
|
|
canvas (np.ndarray): A 3D numpy array representing the canvas (image) on which to draw the hand pose. |
|
|
keypoints (List[Keypoint]| None): A list of Keypoint objects representing the hand keypoints to be drawn |
|
|
or None if no keypoints are present. |
|
|
|
|
|
Returns: |
|
|
np.ndarray: A 3D numpy array representing the modified canvas with the drawn hand pose. |
|
|
|
|
|
Note: |
|
|
The function expects the x and y coordinates of the keypoints to be normalized between 0 and 1. |
|
|
""" |
|
|
|
|
|
new_kep_list = [ |
|
|
"Nose", |
|
|
"Neck", |
|
|
"RShoulder", |
|
|
"RElbow", |
|
|
"RWrist", |
|
|
"LShoulder", |
|
|
"LElbow", |
|
|
"LWrist", |
|
|
"RHip", |
|
|
"RKnee", |
|
|
"RAnkle", |
|
|
"LHip", |
|
|
"LKnee", |
|
|
"LAnkle", |
|
|
"REye", |
|
|
"LEye", |
|
|
"REar", |
|
|
"LEar", |
|
|
"LToe", |
|
|
"RToe", |
|
|
] |
|
|
|
|
|
|
|
|
kp2ds = kp2ds.copy() |
|
|
if not draw_head: |
|
|
kp2ds[[0,14,15,16,17], 2] = 0 |
|
|
kp2ds_body = kp2ds |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
limbSeq = [ |
|
|
[2, 3], |
|
|
[2, 6], |
|
|
[3, 4], |
|
|
[4, 5], |
|
|
[6, 7], |
|
|
[7, 8], |
|
|
[2, 9], |
|
|
[9, 10], |
|
|
[10, 11], |
|
|
[2, 12], |
|
|
[12, 13], |
|
|
[13, 14], |
|
|
[2, 1], |
|
|
[1, 15], |
|
|
[15, 17], |
|
|
[1, 16], |
|
|
[16, 18], |
|
|
[14, 19], |
|
|
[11, 20], |
|
|
] |
|
|
|
|
|
colors = [ |
|
|
[255, 0, 0], |
|
|
[255, 85, 0], |
|
|
[255, 170, 0], |
|
|
[255, 255, 0], |
|
|
[170, 255, 0], |
|
|
[85, 255, 0], |
|
|
[0, 255, 0], |
|
|
[0, 255, 85], |
|
|
[0, 255, 170], |
|
|
[0, 255, 255], |
|
|
[0, 170, 255], |
|
|
[0, 85, 255], |
|
|
[0, 0, 255], |
|
|
[85, 0, 255], |
|
|
[170, 0, 255], |
|
|
[255, 0, 255], |
|
|
[255, 0, 170], |
|
|
[255, 0, 85], |
|
|
|
|
|
[200, 200, 0], |
|
|
[100, 100, 0], |
|
|
] |
|
|
|
|
|
H, W, C = img.shape |
|
|
stickwidth = max(int(min(H, W) / stick_width_norm), 1) |
|
|
|
|
|
for _idx, ((k1_index, k2_index), color) in enumerate(zip(limbSeq, colors)): |
|
|
keypoint1 = kp2ds_body[k1_index - 1] |
|
|
keypoint2 = kp2ds_body[k2_index - 1] |
|
|
|
|
|
if keypoint1[-1] < threshold or keypoint2[-1] < threshold: |
|
|
continue |
|
|
|
|
|
Y = np.array([keypoint1[0], keypoint2[0]]) |
|
|
X = np.array([keypoint1[1], keypoint2[1]]) |
|
|
mX = np.mean(X) |
|
|
mY = np.mean(Y) |
|
|
length = ((X[0] - X[1]) ** 2 + (Y[0] - Y[1]) ** 2) ** 0.5 |
|
|
angle = math.degrees(math.atan2(X[0] - X[1], Y[0] - Y[1])) |
|
|
polygon = cv2.ellipse2Poly((int(mY), int(mX)), (int(length / 2), stickwidth), int(angle), 0, 360, 1) |
|
|
cv2.fillConvexPoly(img, polygon, [int(float(c) * 0.6) for c in color]) |
|
|
|
|
|
for _idx, (keypoint, color) in enumerate(zip(kp2ds_body, colors)): |
|
|
if keypoint[-1] < threshold: |
|
|
continue |
|
|
x, y = keypoint[0], keypoint[1] |
|
|
|
|
|
cv2.circle(img, (int(x), int(y)), stickwidth, color, thickness=-1) |
|
|
|
|
|
if draw_hand: |
|
|
img = draw_handpose(img, kp2ds_lhand, hand_score_th=threshold) |
|
|
img = draw_handpose(img, kp2ds_rhand, hand_score_th=threshold) |
|
|
|
|
|
kp2ds_body[:, 0] /= W |
|
|
kp2ds_body[:, 1] /= H |
|
|
|
|
|
if data_to_json is not None: |
|
|
if idx == -1: |
|
|
data_to_json.append( |
|
|
{ |
|
|
"image_id": "frame_{:05d}.jpg".format(len(data_to_json) + 1), |
|
|
"height": H, |
|
|
"width": W, |
|
|
"category_id": 1, |
|
|
"keypoints_body": kp2ds_body.tolist(), |
|
|
"keypoints_left_hand": kp2ds_lhand.tolist(), |
|
|
"keypoints_right_hand": kp2ds_rhand.tolist(), |
|
|
} |
|
|
) |
|
|
else: |
|
|
data_to_json[idx] = { |
|
|
"image_id": "frame_{:05d}.jpg".format(idx + 1), |
|
|
"height": H, |
|
|
"width": W, |
|
|
"category_id": 1, |
|
|
"keypoints_body": kp2ds_body.tolist(), |
|
|
"keypoints_left_hand": kp2ds_lhand.tolist(), |
|
|
"keypoints_right_hand": kp2ds_rhand.tolist(), |
|
|
} |
|
|
return img |
|
|
|
|
|
|
|
|
def draw_aapose_new( |
|
|
img, |
|
|
kp2ds, |
|
|
threshold=0.6, |
|
|
data_to_json=None, |
|
|
idx=-1, |
|
|
kp2ds_lhand=None, |
|
|
kp2ds_rhand=None, |
|
|
draw_hand=False, |
|
|
stickwidth_type='v2', |
|
|
draw_head=True |
|
|
): |
|
|
""" |
|
|
Draw keypoints and connections representing hand pose on a given canvas. |
|
|
|
|
|
Args: |
|
|
canvas (np.ndarray): A 3D numpy array representing the canvas (image) on which to draw the hand pose. |
|
|
keypoints (List[Keypoint]| None): A list of Keypoint objects representing the hand keypoints to be drawn |
|
|
or None if no keypoints are present. |
|
|
|
|
|
Returns: |
|
|
np.ndarray: A 3D numpy array representing the modified canvas with the drawn hand pose. |
|
|
|
|
|
Note: |
|
|
The function expects the x and y coordinates of the keypoints to be normalized between 0 and 1. |
|
|
""" |
|
|
|
|
|
new_kep_list = [ |
|
|
"Nose", |
|
|
"Neck", |
|
|
"RShoulder", |
|
|
"RElbow", |
|
|
"RWrist", |
|
|
"LShoulder", |
|
|
"LElbow", |
|
|
"LWrist", |
|
|
"RHip", |
|
|
"RKnee", |
|
|
"RAnkle", |
|
|
"LHip", |
|
|
"LKnee", |
|
|
"LAnkle", |
|
|
"REye", |
|
|
"LEye", |
|
|
"REar", |
|
|
"LEar", |
|
|
"LToe", |
|
|
"RToe", |
|
|
] |
|
|
|
|
|
|
|
|
kp2ds = kp2ds.copy() |
|
|
if not draw_head: |
|
|
kp2ds[[0,14,15,16,17], 2] = 0 |
|
|
kp2ds_body = kp2ds |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
limbSeq = [ |
|
|
[2, 3], |
|
|
[2, 6], |
|
|
[3, 4], |
|
|
[4, 5], |
|
|
[6, 7], |
|
|
[7, 8], |
|
|
[2, 9], |
|
|
[9, 10], |
|
|
[10, 11], |
|
|
[2, 12], |
|
|
[12, 13], |
|
|
[13, 14], |
|
|
[2, 1], |
|
|
[1, 15], |
|
|
[15, 17], |
|
|
[1, 16], |
|
|
[16, 18], |
|
|
[14, 19], |
|
|
[11, 20], |
|
|
] |
|
|
|
|
|
colors = [ |
|
|
[255, 0, 0], |
|
|
[255, 85, 0], |
|
|
[255, 170, 0], |
|
|
[255, 255, 0], |
|
|
[170, 255, 0], |
|
|
[85, 255, 0], |
|
|
[0, 255, 0], |
|
|
[0, 255, 85], |
|
|
[0, 255, 170], |
|
|
[0, 255, 255], |
|
|
[0, 170, 255], |
|
|
[0, 85, 255], |
|
|
[0, 0, 255], |
|
|
[85, 0, 255], |
|
|
[170, 0, 255], |
|
|
[255, 0, 255], |
|
|
[255, 0, 170], |
|
|
[255, 0, 85], |
|
|
|
|
|
[200, 200, 0], |
|
|
[100, 100, 0], |
|
|
] |
|
|
|
|
|
H, W, C = img.shape |
|
|
H, W, C = img.shape |
|
|
|
|
|
if stickwidth_type == 'v1': |
|
|
stickwidth = max(int(min(H, W) / 200), 1) |
|
|
elif stickwidth_type == 'v2': |
|
|
stickwidth = max(int(min(H, W) / 200) - 1, 1) |
|
|
else: |
|
|
raise |
|
|
|
|
|
for _idx, ((k1_index, k2_index), color) in enumerate(zip(limbSeq, colors)): |
|
|
keypoint1 = kp2ds_body[k1_index - 1] |
|
|
keypoint2 = kp2ds_body[k2_index - 1] |
|
|
|
|
|
if keypoint1[-1] < threshold or keypoint2[-1] < threshold: |
|
|
continue |
|
|
|
|
|
Y = np.array([keypoint1[0], keypoint2[0]]) |
|
|
X = np.array([keypoint1[1], keypoint2[1]]) |
|
|
mX = np.mean(X) |
|
|
mY = np.mean(Y) |
|
|
length = ((X[0] - X[1]) ** 2 + (Y[0] - Y[1]) ** 2) ** 0.5 |
|
|
angle = math.degrees(math.atan2(X[0] - X[1], Y[0] - Y[1])) |
|
|
polygon = cv2.ellipse2Poly((int(mY), int(mX)), (int(length / 2), stickwidth), int(angle), 0, 360, 1) |
|
|
cv2.fillConvexPoly(img, polygon, [int(float(c) * 0.6) for c in color]) |
|
|
|
|
|
for _idx, (keypoint, color) in enumerate(zip(kp2ds_body, colors)): |
|
|
if keypoint[-1] < threshold: |
|
|
continue |
|
|
x, y = keypoint[0], keypoint[1] |
|
|
|
|
|
cv2.circle(img, (int(x), int(y)), stickwidth, color, thickness=-1) |
|
|
|
|
|
if draw_hand: |
|
|
img = draw_handpose_new(img, kp2ds_lhand, stickwidth_type=stickwidth_type, hand_score_th=threshold) |
|
|
img = draw_handpose_new(img, kp2ds_rhand, stickwidth_type=stickwidth_type, hand_score_th=threshold) |
|
|
|
|
|
kp2ds_body[:, 0] /= W |
|
|
kp2ds_body[:, 1] /= H |
|
|
|
|
|
if data_to_json is not None: |
|
|
if idx == -1: |
|
|
data_to_json.append( |
|
|
{ |
|
|
"image_id": "frame_{:05d}.jpg".format(len(data_to_json) + 1), |
|
|
"height": H, |
|
|
"width": W, |
|
|
"category_id": 1, |
|
|
"keypoints_body": kp2ds_body.tolist(), |
|
|
"keypoints_left_hand": kp2ds_lhand.tolist(), |
|
|
"keypoints_right_hand": kp2ds_rhand.tolist(), |
|
|
} |
|
|
) |
|
|
else: |
|
|
data_to_json[idx] = { |
|
|
"image_id": "frame_{:05d}.jpg".format(idx + 1), |
|
|
"height": H, |
|
|
"width": W, |
|
|
"category_id": 1, |
|
|
"keypoints_body": kp2ds_body.tolist(), |
|
|
"keypoints_left_hand": kp2ds_lhand.tolist(), |
|
|
"keypoints_right_hand": kp2ds_rhand.tolist(), |
|
|
} |
|
|
return img |
|
|
|
|
|
|
|
|
def draw_bbox(img, bbox, color=(255, 0, 0)): |
|
|
img = load_image(img) |
|
|
bbox = [int(bbox_tmp) for bbox_tmp in bbox] |
|
|
cv2.rectangle(img, (bbox[0], bbox[1]), (bbox[2], bbox[3]), color, 2) |
|
|
return img |
|
|
|
|
|
|
|
|
def draw_kp2ds(img, kp2ds, threshold=0, color=(255, 0, 0), skeleton=None, reverse=False): |
|
|
img = load_image(img, reverse) |
|
|
|
|
|
if skeleton is not None: |
|
|
if skeleton == "coco17": |
|
|
skeleton_list = [ |
|
|
[6, 8], |
|
|
[8, 10], |
|
|
[5, 7], |
|
|
[7, 9], |
|
|
[11, 13], |
|
|
[13, 15], |
|
|
[12, 14], |
|
|
[14, 16], |
|
|
[5, 6], |
|
|
[6, 12], |
|
|
[12, 11], |
|
|
[11, 5], |
|
|
] |
|
|
color_list = [ |
|
|
(255, 0, 0), |
|
|
(0, 255, 0), |
|
|
(0, 0, 255), |
|
|
(255, 255, 0), |
|
|
(255, 0, 255), |
|
|
(0, 255, 255), |
|
|
] |
|
|
elif skeleton == "cocowholebody": |
|
|
skeleton_list = [ |
|
|
[6, 8], |
|
|
[8, 10], |
|
|
[5, 7], |
|
|
[7, 9], |
|
|
[11, 13], |
|
|
[13, 15], |
|
|
[12, 14], |
|
|
[14, 16], |
|
|
[5, 6], |
|
|
[6, 12], |
|
|
[12, 11], |
|
|
[11, 5], |
|
|
[15, 17], |
|
|
[15, 18], |
|
|
[15, 19], |
|
|
[16, 20], |
|
|
[16, 21], |
|
|
[16, 22], |
|
|
[91, 92, 93, 94, 95], |
|
|
[91, 96, 97, 98, 99], |
|
|
[91, 100, 101, 102, 103], |
|
|
[91, 104, 105, 106, 107], |
|
|
[91, 108, 109, 110, 111], |
|
|
[112, 113, 114, 115, 116], |
|
|
[112, 117, 118, 119, 120], |
|
|
[112, 121, 122, 123, 124], |
|
|
[112, 125, 126, 127, 128], |
|
|
[112, 129, 130, 131, 132], |
|
|
] |
|
|
color_list = [ |
|
|
(255, 0, 0), |
|
|
(0, 255, 0), |
|
|
(0, 0, 255), |
|
|
(255, 255, 0), |
|
|
(255, 0, 255), |
|
|
(0, 255, 255), |
|
|
] |
|
|
else: |
|
|
color_list = [color] |
|
|
for _idx, _skeleton in enumerate(skeleton_list): |
|
|
for i in range(len(_skeleton) - 1): |
|
|
cv2.line( |
|
|
img, |
|
|
(int(kp2ds[_skeleton[i], 0]), int(kp2ds[_skeleton[i], 1])), |
|
|
(int(kp2ds[_skeleton[i + 1], 0]), int(kp2ds[_skeleton[i + 1], 1])), |
|
|
color_list[_idx % len(color_list)], |
|
|
3, |
|
|
) |
|
|
|
|
|
for _idx, kp2d in enumerate(kp2ds): |
|
|
if kp2d[2] > threshold: |
|
|
cv2.circle(img, (int(kp2d[0]), int(kp2d[1])), 3, color, -1) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return img |
|
|
|
|
|
|
|
|
def draw_mask(img, mask, background=0, return_rgba=False): |
|
|
img = load_image(img) |
|
|
h, w, _ = img.shape |
|
|
if type(background) == int: |
|
|
background = np.ones((h, w, 3)).astype(np.uint8) * 255 * background |
|
|
backgournd = cv2.resize(background, (w, h)) |
|
|
img_rgba = np.concatenate([img, mask], -1) |
|
|
return alphaMerge(img_rgba, background, 0, 0, return_rgba=True) |
|
|
|
|
|
|
|
|
def draw_pcd(pcd_list, save_path=None): |
|
|
fig = plt.figure() |
|
|
ax = fig.add_subplot(111, projection="3d") |
|
|
|
|
|
color_list = ["r", "g", "b", "y", "p"] |
|
|
|
|
|
for _idx, _pcd in enumerate(pcd_list): |
|
|
ax.scatter(_pcd[:, 0], _pcd[:, 1], _pcd[:, 2], c=color_list[_idx], marker="o") |
|
|
|
|
|
ax.set_xlabel("X") |
|
|
ax.set_ylabel("Y") |
|
|
ax.set_zlabel("Z") |
|
|
|
|
|
if save_path is not None: |
|
|
plt.savefig(save_path) |
|
|
else: |
|
|
plt.savefig("tmp.png") |
|
|
|
|
|
|
|
|
def load_image(img, reverse=False): |
|
|
if type(img) == str: |
|
|
img = cv2.imread(img) |
|
|
if reverse: |
|
|
img = img.astype(np.float32) |
|
|
img = img[:, :, ::-1] |
|
|
img = img.astype(np.uint8) |
|
|
return img |
|
|
|
|
|
|
|
|
def draw_skeleten(meta): |
|
|
kps = [] |
|
|
for i, kp in enumerate(meta["keypoints_body"]): |
|
|
if kp is None: |
|
|
|
|
|
kps.append([0, 0, 0]) |
|
|
else: |
|
|
kps.append([*kp, 1]) |
|
|
kps = np.array(kps) |
|
|
|
|
|
kps[:, 0] *= meta["width"] |
|
|
kps[:, 1] *= meta["height"] |
|
|
pose_img = np.zeros([meta["height"], meta["width"], 3], dtype=np.uint8) |
|
|
|
|
|
pose_img = draw_aapose( |
|
|
pose_img, |
|
|
kps, |
|
|
draw_hand=True, |
|
|
kp2ds_lhand=meta["keypoints_left_hand"], |
|
|
kp2ds_rhand=meta["keypoints_right_hand"], |
|
|
) |
|
|
return pose_img |
|
|
|
|
|
|
|
|
def draw_skeleten_with_pncc(pncc: np.ndarray, meta: Dict) -> np.ndarray: |
|
|
""" |
|
|
Args: |
|
|
pncc: [H,W,3] |
|
|
meta: required keys: keypoints_body: [N, 3] keypoints_left_hand, keypoints_right_hand |
|
|
Return: |
|
|
np.ndarray [H, W, 3] |
|
|
""" |
|
|
|
|
|
kps = [] |
|
|
for i, kp in enumerate(meta["keypoints_body"]): |
|
|
if kp is None: |
|
|
|
|
|
kps.append([0, 0, 0]) |
|
|
elif i in [14, 15, 16, 17]: |
|
|
kps.append([0, 0, 0]) |
|
|
else: |
|
|
kps.append([*kp]) |
|
|
kps = np.stack(kps) |
|
|
|
|
|
kps[:, 0] *= pncc.shape[1] |
|
|
kps[:, 1] *= pncc.shape[0] |
|
|
|
|
|
|
|
|
canvas = np.zeros_like(pncc) |
|
|
if kps[0][2] > 0.6 and kps[1][2] > 0.6: |
|
|
canvas = draw_ellipse_by_2kp(canvas, kps[0], kps[1], [0, 0, 255]) |
|
|
|
|
|
|
|
|
mask = (pncc > 0).max(axis=2) |
|
|
canvas[mask] = pncc[mask] |
|
|
pncc = canvas |
|
|
|
|
|
|
|
|
kps[0] = 0 |
|
|
|
|
|
meta["keypoints_left_hand"][:, 0] *= meta["width"] |
|
|
meta["keypoints_left_hand"][:, 1] *= meta["height"] |
|
|
|
|
|
meta["keypoints_right_hand"][:, 0] *= meta["width"] |
|
|
meta["keypoints_right_hand"][:, 1] *= meta["height"] |
|
|
pose_img = draw_aapose( |
|
|
pncc, |
|
|
kps, |
|
|
draw_hand=True, |
|
|
kp2ds_lhand=meta["keypoints_left_hand"], |
|
|
kp2ds_rhand=meta["keypoints_right_hand"], |
|
|
) |
|
|
return pose_img |
|
|
|
|
|
|
|
|
FACE_CUSTOM_STYLE = { |
|
|
"eyeball": {"indexs": [68, 69], "color": [255, 255, 255], "connect": False}, |
|
|
"left_eyebrow": {"indexs": [17, 18, 19, 20, 21], "color": [0, 255, 0]}, |
|
|
"right_eyebrow": {"indexs": [22, 23, 24, 25, 26], "color": [0, 0, 255]}, |
|
|
"left_eye": {"indexs": [36, 37, 38, 39, 40, 41], "color": [255, 255, 0], "close": True}, |
|
|
"right_eye": {"indexs": [42, 43, 44, 45, 46, 47], "color": [255, 0, 255], "close": True}, |
|
|
"mouth_outside": {"indexs": list(range(48, 60)), "color": [100, 255, 50], "close": True}, |
|
|
"mouth_inside": {"indexs": [60, 61, 62, 63, 64, 65, 66, 67], "color": [255, 100, 50], "close": True}, |
|
|
} |
|
|
|
|
|
|
|
|
def draw_face_kp(img, kps, thickness=2, style=FACE_CUSTOM_STYLE): |
|
|
""" |
|
|
Args: |
|
|
img: [H, W, 3] |
|
|
kps: [70, 2] |
|
|
""" |
|
|
img = img.copy() |
|
|
for key, item in style.items(): |
|
|
pts = np.array(kps[item["indexs"]]).astype(np.int32) |
|
|
connect = item.get("connect", True) |
|
|
color = item["color"] |
|
|
close = item.get("close", False) |
|
|
if connect: |
|
|
cv2.polylines(img, [pts], close, color, thickness=thickness) |
|
|
else: |
|
|
for kp in pts: |
|
|
kp = np.array(kp).astype(np.int32) |
|
|
cv2.circle(img, kp, thickness * 2, color=color, thickness=-1) |
|
|
return img |
|
|
|
|
|
|
|
|
def draw_traj(metas: List[AAPoseMeta], threshold=0.6): |
|
|
|
|
|
colors = [[255, 0, 0], [255, 85, 0], [255, 170, 0], [255, 255, 0], [170, 255, 0], [85, 255, 0], [0, 255, 0], \ |
|
|
[0, 255, 85], [0, 255, 170], [0, 255, 255], [0, 170, 255], [0, 85, 255], [0, 0, 255], [85, 0, 255], \ |
|
|
[170, 0, 255], [255, 0, 255], [255, 0, 170], [255, 0, 85], [100, 255, 50], [255, 100, 50], |
|
|
|
|
|
[200, 200, 0], |
|
|
[100, 100, 0] |
|
|
] |
|
|
limbSeq = [ |
|
|
[1, 2], [1, 5], |
|
|
[2, 3], [3, 4], |
|
|
[5, 6], [6, 7], |
|
|
[1, 8], [8, 9], [9, 10], |
|
|
[1, 11], [11, 12], [12, 13], |
|
|
|
|
|
[13, 18], [10, 19] |
|
|
] |
|
|
|
|
|
face_seq = [[1, 0], [0, 14], [14, 16], [0, 15], [15, 17]] |
|
|
kp_body = np.array([meta.kps_body for meta in metas]) |
|
|
kp_body_p = np.array([meta.kps_body_p for meta in metas]) |
|
|
|
|
|
|
|
|
face_seq = random.sample(face_seq, 2) |
|
|
|
|
|
kp_lh = np.array([meta.kps_lhand for meta in metas]) |
|
|
kp_rh = np.array([meta.kps_rhand for meta in metas]) |
|
|
|
|
|
kp_lh_p = np.array([meta.kps_lhand_p for meta in metas]) |
|
|
kp_rh_p = np.array([meta.kps_rhand_p for meta in metas]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
new_limbSeq = [] |
|
|
key_point_list = [] |
|
|
for _idx, ((k1_index, k2_index)) in enumerate(limbSeq): |
|
|
|
|
|
vis = (kp_body_p[:, k1_index] > threshold) * (kp_body_p[:, k2_index] > threshold) * 1 |
|
|
if vis.sum() * 1.0 / vis.shape[0] > 0.4: |
|
|
new_limbSeq.append([k1_index, k2_index]) |
|
|
|
|
|
for _idx, ((k1_index, k2_index)) in enumerate(limbSeq): |
|
|
|
|
|
keypoint1 = kp_body[:, k1_index - 1] |
|
|
keypoint2 = kp_body[:, k2_index - 1] |
|
|
interleave = random.randint(4, 7) |
|
|
randind = random.randint(0, interleave - 1) |
|
|
|
|
|
|
|
|
Y = np.array([keypoint1[:, 0], keypoint2[:, 0]]) |
|
|
X = np.array([keypoint1[:, 1], keypoint2[:, 1]]) |
|
|
|
|
|
vis = (keypoint1[:, -1] > threshold) * (keypoint2[:, -1] > threshold) * 1 |
|
|
|
|
|
|
|
|
t = randind / interleave |
|
|
x = (1-t)*Y[0, :] + t*Y[1, :] |
|
|
y = (1-t)*X[0, :] + t*X[1, :] |
|
|
|
|
|
|
|
|
x = x.astype(int) |
|
|
y = y.astype(int) |
|
|
|
|
|
new_array = np.array([x, y, vis]).T |
|
|
|
|
|
key_point_list.append(new_array) |
|
|
|
|
|
indx_lh = random.randint(0, kp_lh.shape[1] - 1) |
|
|
lh = kp_lh[:, indx_lh, :] |
|
|
lh_p = kp_lh_p[:, indx_lh:indx_lh+1] |
|
|
lh = np.concatenate([lh, lh_p], axis=-1) |
|
|
|
|
|
indx_rh = random.randint(0, kp_rh.shape[1] - 1) |
|
|
rh = kp_rh[:, random.randint(0, kp_rh.shape[1] - 1), :] |
|
|
rh_p = kp_rh_p[:, indx_rh:indx_rh+1] |
|
|
rh = np.concatenate([rh, rh_p], axis=-1) |
|
|
|
|
|
|
|
|
|
|
|
lh[-1, :] = (lh[-1, :] > threshold) * 1 |
|
|
rh[-1, :] = (rh[-1, :] > threshold) * 1 |
|
|
|
|
|
|
|
|
|
|
|
key_point_list.append(lh.astype(int)) |
|
|
key_point_list.append(rh.astype(int)) |
|
|
|
|
|
|
|
|
key_points_list = np.stack(key_point_list) |
|
|
num_points = len(key_points_list) |
|
|
sample_colors = random.sample(colors, num_points) |
|
|
|
|
|
stickwidth = max(int(min(metas[0].width, metas[0].height) / 150), 2) |
|
|
|
|
|
image_list_ori = [] |
|
|
for i in range(key_points_list.shape[-2]): |
|
|
_image_vis = np.zeros((metas[0].width, metas[0].height, 3)) |
|
|
points = key_points_list[:, i, :] |
|
|
for idx, point in enumerate(points): |
|
|
x, y, vis = point |
|
|
if vis == 1: |
|
|
cv2.circle(_image_vis, (x, y), stickwidth, sample_colors[idx], thickness=-1) |
|
|
|
|
|
image_list_ori.append(_image_vis) |
|
|
|
|
|
return image_list_ori |
|
|
|
|
|
return [np.zeros([meta.width, meta.height, 3], dtype=np.uint8) for meta in metas] |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
meta = { |
|
|
"image_id": "00472.jpg", |
|
|
"height": 540, |
|
|
"width": 414, |
|
|
"category_id": 1, |
|
|
"keypoints_body": [ |
|
|
[0.5084776947463768, 0.11350188078703703], |
|
|
[0.504467655495169, 0.20419560185185184], |
|
|
[0.3982016153381642, 0.198046875], |
|
|
[0.3841664779589372, 0.34869068287037036], |
|
|
[0.3901815368357488, 0.4670536747685185], |
|
|
[0.610733695652174, 0.2103443287037037], |
|
|
[0.6167487545289855, 0.3517650462962963], |
|
|
[0.6448190292874396, 0.4762767650462963], |
|
|
[0.4523371452294686, 0.47320240162037036], |
|
|
[0.4503321256038647, 0.6776475694444445], |
|
|
[0.47639738073671495, 0.8544234664351852], |
|
|
[0.5766483620169082, 0.47320240162037036], |
|
|
[0.5666232638888888, 0.6761103877314815], |
|
|
[0.534542949879227, 0.863646556712963], |
|
|
[0.4864224788647343, 0.09505570023148148], |
|
|
[0.5285278910024155, 0.09351851851851851], |
|
|
[0.46236224335748793, 0.10581597222222222], |
|
|
[0.5586031853864735, 0.10274160879629629], |
|
|
[0.4994551064311594, 0.9405056423611111], |
|
|
[0.4152442821557971, 0.9312825520833333], |
|
|
], |
|
|
"keypoints_left_hand": [ |
|
|
[267.78515625, 263.830078125, 1.2840936183929443], |
|
|
[265.294921875, 269.640625, 1.2546794414520264], |
|
|
[263.634765625, 277.111328125, 1.2863062620162964], |
|
|
[262.8046875, 285.412109375, 1.267038345336914], |
|
|
[261.14453125, 292.8828125, 1.280144453048706], |
|
|
[273.595703125, 281.26171875, 1.2592815160751343], |
|
|
[271.10546875, 291.22265625, 1.3256099224090576], |
|
|
[265.294921875, 294.54296875, 1.2368024587631226], |
|
|
[261.14453125, 294.54296875, 0.9771889448165894], |
|
|
[274.42578125, 282.091796875, 1.250044584274292], |
|
|
[269.4453125, 291.22265625, 1.2571144104003906], |
|
|
[264.46484375, 292.8828125, 1.177802324295044], |
|
|
[260.314453125, 292.052734375, 0.9283463358879089], |
|
|
[273.595703125, 282.091796875, 1.1834490299224854], |
|
|
[269.4453125, 290.392578125, 1.188171625137329], |
|
|
[265.294921875, 290.392578125, 1.192609429359436], |
|
|
[261.974609375, 289.5625, 0.9366656541824341], |
|
|
[271.935546875, 281.26171875, 1.0946396589279175], |
|
|
[268.615234375, 287.072265625, 0.9906131029129028], |
|
|
[265.294921875, 287.90234375, 1.0219476222991943], |
|
|
[262.8046875, 287.072265625, 0.9240120053291321], |
|
|
], |
|
|
"keypoints_right_hand": [ |
|
|
[161.53515625, 258.849609375, 1.2069408893585205], |
|
|
[168.17578125, 263.0, 1.1846840381622314], |
|
|
[173.986328125, 269.640625, 1.1435924768447876], |
|
|
[173.986328125, 277.94140625, 1.1802611351013184], |
|
|
[173.986328125, 286.2421875, 1.2599592208862305], |
|
|
[165.685546875, 275.451171875, 1.0633569955825806], |
|
|
[167.345703125, 286.2421875, 1.1693341732025146], |
|
|
[169.8359375, 291.22265625, 1.2698509693145752], |
|
|
[170.666015625, 294.54296875, 1.0619274377822876], |
|
|
[160.705078125, 276.28125, 1.0995020866394043], |
|
|
[163.1953125, 287.90234375, 1.2735884189605713], |
|
|
[166.515625, 291.22265625, 1.339503526687622], |
|
|
[169.005859375, 294.54296875, 1.0835273265838623], |
|
|
[157.384765625, 277.111328125, 1.0866981744766235], |
|
|
[161.53515625, 287.072265625, 1.2468621730804443], |
|
|
[164.025390625, 289.5625, 1.2817761898040771], |
|
|
[166.515625, 292.052734375, 1.099466323852539], |
|
|
[155.724609375, 277.111328125, 1.1065717935562134], |
|
|
[159.044921875, 285.412109375, 1.1924479007720947], |
|
|
[160.705078125, 287.072265625, 1.1304771900177002], |
|
|
[162.365234375, 287.90234375, 1.0040509700775146], |
|
|
], |
|
|
} |
|
|
demo_meta = AAPoseMeta(meta) |
|
|
res = draw_traj([demo_meta]*5) |
|
|
cv2.imwrite("traj.png", res[0][..., ::-1]) |
|
|
|