SCAIL-2 / SCAIL-Pose /pose_draw /draw_3d_utils.py
fffiloni's picture
Migrated files batch 1
09462dc verified
Raw
History Blame Contribute Delete
10.1 kB
import numpy as np
def convert_3dpose_to_2dpose_body(body_keypoints, face_keypoints):
"""
将20点的3D坐标映射到18点的2D坐标。
:param poses: 输入的20点坐标列表,每个点为 [x, y, z]
:return: 映射得到的18点坐标列表,每个点为 [x, y]
"""
# 映射关系:索引位置
body_mapping = {
0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 8, 9: 9, 10: 10, 11: 23, 13: 22, 12: 21,
14: 11, 15: 12, 16: 13, 17: 20, 18: 18, 19: 19
}
face_mapping = {
1: 16, 8: 14, 4: 0, 7: 15, 0: 17
}
# 初始化18点坐标列表,默认值为 [-1, -1]
result = [[-1, -1] for _ in range(24)]
# 遍历映射关系,将对应的20点坐标映射到18点坐标
for src_idx, dst_idx in body_mapping.items():
if src_idx < len(body_keypoints): # 确保索引不越界
result[dst_idx] = [body_keypoints[src_idx][1],body_keypoints[src_idx][0]] # 提取 x, y 坐标
for src_idx, dst_idx in face_mapping.items():
if src_idx < len(face_keypoints):
result[dst_idx] = [face_keypoints[src_idx][1], face_keypoints[src_idx][0]]
return result
def convert_3dpose_to_2dpose_hand(left_hand_keypoints, right_hand_keypoints, body_keypoints):
"""
将20点的3D坐标映射到18点的2D坐标。
:param poses: 输入的20点坐标列表,每个点为 [x, y, z]
:return: 映射得到的18点坐标列表,每个点为 [x, y]
"""
# 映射关系:索引位置
hand_mapping = {
0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10,
10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18,
18: 19, 19: 20
}
body_mapping_left = {3: 0}
body_mapping_right = {6: 0}
# 初始化18点坐标列表,默认值为 [-1, -1]
left_result = [[-1, -1] for _ in range(21)]
right_result = [[-1, -1] for _ in range(21)]
# 遍历映射关系,将对应的20点坐标映射到18点坐标
for src_idx, dst_idx in hand_mapping.items():
if src_idx < len(left_hand_keypoints): # 确保索引不越界
left_result[dst_idx] = [left_hand_keypoints[src_idx][1], left_hand_keypoints[src_idx][0]] # 提取 x, y 坐标
right_result[dst_idx] = [right_hand_keypoints[src_idx][1], right_hand_keypoints[src_idx][0]]
for src_idx, dst_idx in body_mapping_left.items():
if src_idx < len(body_keypoints):
left_result[dst_idx] = [body_keypoints[src_idx][1], body_keypoints[src_idx][0]]
for src_idx, dst_idx in body_mapping_right.items():
if src_idx < len(body_keypoints):
right_result[dst_idx] = [body_keypoints[src_idx][1], body_keypoints[src_idx][0]]
return [left_result, right_result]
def convert_3dpose_to_2dpose_face(face_keypoints):
result = [[-1, -1] if i in [0, 1, 4, 5, 6, 7, 8] else [pt[1], pt[0]] for i, pt in enumerate(face_keypoints)]
return result
def correct_lift_end_kpt_by_phmr(start, end, dwpose_kpts, lift_start, lift_end, phmr_start, phmr_end):
'''
检查另一端是否符合要求, 符合要求则返回lift后结果,不然返回phmr结果
'''
if dwpose_kpts[start][0] == -1:
return
lift_vec = np.array(lift_end) - np.array(lift_start)
phmr_vec = np.array(phmr_end) - np.array(phmr_start)
start_distance = np.linalg.norm(np.array(lift_start) - np.array(phmr_start))
end_distance = np.linalg.norm(np.array(lift_end) - np.array(phmr_end))
lift_vec_len = np.linalg.norm(lift_vec)
phmr_vec_len = np.linalg.norm(phmr_vec)
if start_distance + end_distance > phmr_vec_len:
dwpose_kpts[end] = [-1, -1]
theta = np.arccos(np.dot(lift_vec, phmr_vec) / (lift_vec_len * phmr_vec_len))
if lift_vec_len > phmr_vec_len * 1.65 or lift_vec_len < phmr_vec_len * 0.4 or theta > np.pi / 4:
dwpose_kpts[end] = [-1, -1]
return
def mix_3d_poses(poses_dwpose, poses_3dpose):
'''
组合两种pose,用3dPose的身体,DWPose的face和hand
'''
poses = []
for pose_dwpose, pose_3dpose in zip(poses_dwpose, poses_3dpose):
pose = {
"bodies": {
"candidate": pose_3dpose["bodies"]["candidate"],
"subset": pose_dwpose["bodies"]["subset"]
},
"faces": pose_dwpose["faces"],
"hands": pose_dwpose["hands"]
}
poses.append(pose)
return poses
def correct_hand_from_3d(hand_keypoints_dwpose, hand_keypoints_3dpose):
'''
如果dwpose的手部关节点和3dpose的手部关节点相差过大,则去掉最远的那一端
'''
edges_palm = [
[1, 2], [2, 3], [3, 4],
[5, 6], [6, 7], [7, 8],
[9, 10], [10, 11], [11, 12],
[13, 14], [14, 15], [15, 16],
[17, 18], [18, 19], [19, 20],
]
edges_finger = [[0, 1], [0, 5], [0, 9], [0, 13], [0, 17]]
max_length_palm = 0
max_length_finger = 0
for edge in edges_palm:
limb_length_3dpose = np.linalg.norm(np.array(hand_keypoints_3dpose[edge[0]]) - np.array(hand_keypoints_3dpose[edge[1]]))
if limb_length_3dpose > max_length_palm:
max_length_palm = limb_length_3dpose
for edge in edges_finger:
limb_length_3dpose = np.linalg.norm(np.array(hand_keypoints_3dpose[edge[0]]) - np.array(hand_keypoints_3dpose[edge[1]]))
if limb_length_3dpose > max_length_finger:
max_length_finger = limb_length_3dpose
for edge in edges_palm:
limb_length_dwpose = np.linalg.norm(np.array(hand_keypoints_dwpose[edge[0]]) - np.array(hand_keypoints_dwpose[edge[1]]))
if limb_length_dwpose > max_length_palm * 1.5:
if -1 in hand_keypoints_dwpose[edge[0]] or -1 in hand_keypoints_dwpose[edge[1]] or -1 in hand_keypoints_3dpose[edge[0]] or -1 in hand_keypoints_3dpose[edge[1]]:
continue
distance_point_0 = np.linalg.norm(np.array(hand_keypoints_dwpose[edge[0]]) - np.array(hand_keypoints_3dpose[edge[0]]))
distance_point_1 = np.linalg.norm(np.array(hand_keypoints_dwpose[edge[1]]) - np.array(hand_keypoints_3dpose[edge[1]]))
if distance_point_0 > distance_point_1:
hand_keypoints_dwpose[edge[1]] = [-1, -1]
else:
hand_keypoints_dwpose[edge[0]] = [-1, -1]
for edge in edges_finger:
limb_length_dwpose = np.linalg.norm(np.array(hand_keypoints_dwpose[edge[0]]) - np.array(hand_keypoints_dwpose[edge[1]]))
if limb_length_dwpose > max_length_finger * 1.5:
if -1 in hand_keypoints_dwpose[edge[0]] or -1 in hand_keypoints_dwpose[edge[1]] or -1 in hand_keypoints_3dpose[edge[0]] or -1 in hand_keypoints_3dpose[edge[1]]:
continue
distance_point_0 = np.linalg.norm(np.array(hand_keypoints_dwpose[edge[0]]) - np.array(hand_keypoints_3dpose[edge[0]]))
distance_point_1 = np.linalg.norm(np.array(hand_keypoints_dwpose[edge[1]]) - np.array(hand_keypoints_3dpose[edge[1]]))
if distance_point_0 > distance_point_1:
hand_keypoints_dwpose[edge[1]] = [-1, -1]
else:
hand_keypoints_dwpose[edge[0]] = [-1, -1]
return hand_keypoints_dwpose
def correct_body_from_3d(body_keypoints_dwpose, body_keypoints_3dpose, subset_dwpose, subset_3dpose):
'''
如果dwpose的骨骼长度和3dpose的骨骼长度相差过大,则去掉最远的那一端
'''
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],
[3, 17],
[6, 18],
]
for ori_limb in limbSeq:
limb = [ori_limb[0] - 1, ori_limb[1] - 1]
limb_length_dwpose = np.linalg.norm(np.array(body_keypoints_dwpose[limb[0]]) - np.array(body_keypoints_dwpose[limb[1]]))
limb_length_3dpose = np.linalg.norm(np.array(body_keypoints_3dpose[limb[0]]) - np.array(body_keypoints_3dpose[limb[1]]))
if subset_dwpose[0][limb[0]] == -1 or subset_dwpose[0][limb[1]] == -1 or subset_3dpose[0][limb[0]] == -1 or subset_3dpose[0][limb[1]] == -1:
continue
if limb_length_dwpose > limb_length_3dpose * 2:
# 判断较远端
distance_point_0 = np.linalg.norm(np.array(body_keypoints_dwpose[limb[0]]) - np.array(body_keypoints_3dpose[limb[0]]))
distance_point_1 = np.linalg.norm(np.array(body_keypoints_dwpose[limb[1]]) - np.array(body_keypoints_3dpose[limb[1]]))
if distance_point_0 > distance_point_1:
if limb[1] == 1: # 核心
continue
body_keypoints_dwpose[limb[1]] = [-1, -1]
subset_dwpose[0][limb[1]] = -1
else:
if limb[0] == 1: # 核心
continue
body_keypoints_dwpose[limb[0]] = [-1, -1]
subset_dwpose[0][limb[0]] = -1
return body_keypoints_dwpose, subset_dwpose
def correct_full_pose_from_3d(poses_dwpose, poses_3dpose):
'''
如果dwpose的骨骼长度和3dpose的骨骼长度相差过大,则去掉离3d pose最远的那一端
'''
poses = []
for pose_dwpose, pose_3dpose in zip(poses_dwpose, poses_3dpose):
new_candidate, new_subset = correct_body_from_3d(pose_dwpose["bodies"]["candidate"], pose_3dpose["bodies"]["candidate"], pose_dwpose["bodies"]["subset"], pose_3dpose["bodies"]["subset"])
new_hands_0 = correct_hand_from_3d(pose_dwpose["hands"][0], pose_3dpose["hands"][0])
new_hands_1 = correct_hand_from_3d(pose_dwpose["hands"][1], pose_3dpose["hands"][1])
pose = {
"bodies": {
"candidate": new_candidate,
"subset": new_subset
},
"faces": pose_dwpose["faces"],
"hands": [new_hands_0, new_hands_1]
}
poses.append(pose)
return poses