File size: 10,058 Bytes
9b69558
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
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