File size: 4,334 Bytes
ec24258
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import numpy as np
from sklearn import metrics


class AngleMAE:
    """Class for evaluation metrics AngleMAE which computes mean absolute
    error between set of joints angle of reference and test video keypoints

      Parameters:
        ref_keypoits : A numpy array [n, 1, 17, 3] containing keypoints
        representing poses in reference video
        test_keypoits : A numpy array [n, 1, 17, 3] containing keypoints
        representing poses in test video
    """

    def __init__(self):

        self.joints_array = np.array(
            [[11, 5, 7],
             [12, 6, 8],
             [6, 8, 10],
             [5, 7, 9],
             [11, 12, 14],
             [12, 11, 13],
             [12, 14, 16],
             [11, 13, 15],
             [5, 11, 13]]
            )

        self.joints_dict = {
            'left_shoulder_joint': ['left_hip', 'left_shoulder', 'left_elbow'],
            'right_shoulder_joint': ['right_hip', 'right_shoulder',
                                     'right_elbow'],
            'right_elbow_joint': ['right_shoulder', 'right_elbow',
                                  'right_wrist'],
            'left_elbow_joint': ['left_shoulder', 'left_elbow', 'left_wrist'],
            'right_hip_joint': ['left_hip', 'right_hip', 'right_knee'],
            'left_hip_joint': ['right_hip', 'left_hip', 'left_knee'],
            'right_knee_joint': ['right_hip', 'right_knee', 'right_ankle'],
            'left_knee_joint': ['left_hip', 'left_knee', 'left_ankle'],
            'waist_joint': ['left_shoulder', 'left_hip', 'left_knee']
            }

        self.angle_mae_joints_weightage_array = ([1, 1, 1, 1, 1, 1, 1, 1, 1])

    def mean_absolute_error(self, ref_keypoints, test_keypoints) -> object:
        """
        Calcultes MAE of given joints via index between reference and test
        frames

        Args:
          ref_keypoints: ndarray of shape (17,2) containing reference frame
          x, y coordinates
          test_keypoints: ndarray of shape (17,2) containing test frame x,
          y coordinates

        Returns:
          MAE: A float value representing angle based MAE
        """

        ref_angle = self.calculate_angle_atan2(ref_keypoints)
        test_angle = self.calculate_angle_atan2(test_keypoints)

        diff = np.abs(ref_angle - test_angle)

        mae = np.sum(diff * self.angle_mae_joints_weightage_array) / sum(
            self.angle_mae_joints_weightage_array
            )

        return mae

    def calculate_angle_atan2(self, kpts):
        """
        Calcultes angle of given joint

        Args:
          kpts: ndarray of shape (17,2) containing x, y coordinates

        Returns:
          angle: A float value representing angle in degrees
        """
        a = np.zeros((9, 2))
        b = np.zeros((9, 2))
        c = np.zeros((9, 2))

        for i, j in enumerate(self.joints_array):

            a[i] = kpts[j[0]]
            b[i] = kpts[j[1]]
            c[i] = kpts[j[2]]

        vector_b_a = b - a
        vector_b_c = b - c

        angle_0 = np.arctan2(
            vector_b_a[:, 1],
            vector_b_a[:, 0]
            )

        angle_2 = np.arctan2(
            vector_b_c[:, 1],
            vector_b_c[:, 0]
            )

        determinant = vector_b_a[:, 0] * vector_b_c[:, 1] - vector_b_a[:,
                                                            1] * vector_b_c[:,
                                                                 0]

        angle_diff = (angle_0 - angle_2)

        angle = np.degrees(angle_diff)
        joints_angle_array = angle * (determinant < 0) + (360 + angle) * (
            determinant > 0)

        return joints_angle_array % 360


class MAE:
    def __init__(self):
        pass

    @staticmethod
    def mean_absolute_error(ref_keypoints, test_keypoints):
        """
        Calcultes MAE of given keypoints between reference and test frames

        Args:
          ref_keypoints: ndarray of shape (17,2) containing reference frame
          x, y coordinates
          test_keypoints: ndarray of shape (17,2) containing test frame x,
          y coordinates

        Returns:
          MAE: A float value representing MAE
        """
        return metrics.mean_absolute_error(
            ref_keypoints.flatten(),
            test_keypoints.flatten(),
            )