laurenok24
commited on
Commit
•
2114261
1
Parent(s):
0b41ec0
Upload 16 files
Browse files- .gitattributes +7 -0
- 01_10.mp4 +3 -0
- 01_11.mp4 +3 -0
- 01_140.mp4 +3 -0
- 01_16.mp4 +3 -0
- 01_33.mp4 +3 -0
- 01_40.mov +3 -0
- 01_76.mp4 +3 -0
- dive_recognition_functions.py +351 -0
- generate_reports.py +551 -0
- platform.png +0 -0
- pose_estimation.png +0 -0
- report_template_tables.html +149 -0
- scoring_functions.py +579 -0
- splash.png +0 -0
- tempSegAndAllErrorsForAllFrames.py +201 -0
- tempSegAndAllErrorsForAllFrames_newVids.py +312 -0
.gitattributes
CHANGED
@@ -33,3 +33,10 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
01_10.mp4 filter=lfs diff=lfs merge=lfs -text
|
37 |
+
01_11.mp4 filter=lfs diff=lfs merge=lfs -text
|
38 |
+
01_140.mp4 filter=lfs diff=lfs merge=lfs -text
|
39 |
+
01_16.mp4 filter=lfs diff=lfs merge=lfs -text
|
40 |
+
01_33.mp4 filter=lfs diff=lfs merge=lfs -text
|
41 |
+
01_40.mov filter=lfs diff=lfs merge=lfs -text
|
42 |
+
01_76.mp4 filter=lfs diff=lfs merge=lfs -text
|
01_10.mp4
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:4c6723fdcc6e1749ec60a76357db49dfcd4d152e6546c1927614854cc0b990f3
|
3 |
+
size 1303693
|
01_11.mp4
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:ac78a8b402e1eb8be9a2d57e74f239677c4f70649476ad556e83c0851b94e77c
|
3 |
+
size 2621440
|
01_140.mp4
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:c3bbec0ec1ede19c4d93208ece51bf4c08f7889864a8adb31a4d9535f4cc0599
|
3 |
+
size 2621440
|
01_16.mp4
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:f708564d62eb74888e5d62c851b5c63cdda6e6dc2c2d3a6f04f6605e3b8263c6
|
3 |
+
size 2474745
|
01_33.mp4
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:26a28bb4634266170a39c7828f3f7d0017df151a828e77a491cf58dd2eaf814f
|
3 |
+
size 2621440
|
01_40.mov
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:8a7468bc1e790f101608b0648604573fa5e76e89dc861f9a05d03a8538174a8d
|
3 |
+
size 2621440
|
01_76.mp4
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:bfde107e6b7b4b9e813a963b668ba772bed5d4bf16633cf0fb350b6ea5318d6c
|
3 |
+
size 2621440
|
dive_recognition_functions.py
ADDED
@@ -0,0 +1,351 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pickle
|
2 |
+
import numpy as np
|
3 |
+
import os
|
4 |
+
import math
|
5 |
+
from scipy.signal import find_peaks
|
6 |
+
from matplotlib import pyplot as plt
|
7 |
+
|
8 |
+
def get_scale_factor(dive_data):
|
9 |
+
# distance between thorax and pelvis
|
10 |
+
distances = []
|
11 |
+
for pose_pred in dive_data['pose_pred']:
|
12 |
+
if pose_pred is not None:
|
13 |
+
distances.append(math.dist(pose_pred[0][6], pose_pred[0][7]))
|
14 |
+
distances.sort()
|
15 |
+
return np.median(distances)
|
16 |
+
|
17 |
+
def find_angle(vector1, vector2):
|
18 |
+
unit_vector_1 = vector1 / np.linalg.norm(vector1)
|
19 |
+
unit_vector_2 = vector2 / np.linalg.norm(vector2)
|
20 |
+
dot_product = np.dot(unit_vector_1, unit_vector_2)
|
21 |
+
angle = math.degrees(np.arccos(dot_product))
|
22 |
+
return angle
|
23 |
+
|
24 |
+
def is_back_facing(dive_data, board_side):
|
25 |
+
directions = []
|
26 |
+
for i in range(len(dive_data['pose_pred'])):
|
27 |
+
pose_pred = dive_data['pose_pred'][i]
|
28 |
+
if pose_pred is None or dive_data['above_boards'][i] == 0:
|
29 |
+
continue
|
30 |
+
pose_pred = pose_pred[0]
|
31 |
+
|
32 |
+
## left knee bend ###
|
33 |
+
l_knee = pose_pred[4]
|
34 |
+
l_ankle = pose_pred[5]
|
35 |
+
l_hip = pose_pred[3]
|
36 |
+
l_knee_ankle = [l_ankle[0] - l_knee[0], 0-(l_ankle[1] - l_knee[1])]
|
37 |
+
l_knee_hip = [l_hip[0] - l_knee[0], 0-(l_hip[1] - l_knee[1])]
|
38 |
+
l_direction = rotation_direction(l_knee_hip, l_knee_ankle)
|
39 |
+
|
40 |
+
## right knee bend ###
|
41 |
+
r_knee = pose_pred[1]
|
42 |
+
r_ankle = pose_pred[0]
|
43 |
+
r_hip = pose_pred[2]
|
44 |
+
r_knee_ankle = [r_ankle[0] - r_knee[0], 0-(r_ankle[1] - r_knee[1])]
|
45 |
+
r_knee_hip = [r_hip[0] - r_knee[0], 0-(r_hip[1] - r_knee[1])]
|
46 |
+
r_direction = rotation_direction(r_knee_hip, r_knee_ankle)
|
47 |
+
if l_direction == r_direction and l_direction != 0 and board_side == 'left':
|
48 |
+
# we're looking for more clockwise
|
49 |
+
return l_direction < 0
|
50 |
+
elif l_direction == r_direction and l_direction != 0:
|
51 |
+
# we're looking for more counterclockwise
|
52 |
+
return l_direction > 0
|
53 |
+
return False
|
54 |
+
|
55 |
+
def rotation_direction(vector1, vector2, threshold=0.4):
|
56 |
+
# Calculate the determinant to determine rotation direction
|
57 |
+
determinant = vector1[0] * vector2[1] - vector1[1] * vector2[0]
|
58 |
+
mag1= np.linalg.norm(vector1)
|
59 |
+
mag2= np.linalg.norm(vector2)
|
60 |
+
norm_det = determinant/(mag1*mag2)
|
61 |
+
# print("determinant", determinant/(mag1*mag2))
|
62 |
+
# print(norm_det)
|
63 |
+
if norm_det > threshold:
|
64 |
+
# return "counterclockwise"
|
65 |
+
return 1
|
66 |
+
elif norm_det < 0-threshold:
|
67 |
+
# return "clockwise"
|
68 |
+
return -1
|
69 |
+
else:
|
70 |
+
# return "not determinent"
|
71 |
+
return 0
|
72 |
+
|
73 |
+
def find_position(dive_data):
|
74 |
+
angles = []
|
75 |
+
three_in_a_row = 0
|
76 |
+
for i in range(1, len(dive_data['pose_pred'])):
|
77 |
+
pose_pred = dive_data['pose_pred'][i]
|
78 |
+
if pose_pred is None or dive_data['som'][i]==0:
|
79 |
+
continue
|
80 |
+
pose_pred = pose_pred[0]
|
81 |
+
l_knee = pose_pred[4]
|
82 |
+
l_ankle = pose_pred[5]
|
83 |
+
l_hip = pose_pred[3]
|
84 |
+
l_knee_ankle = [l_ankle[0] - l_knee[0], 0-(l_ankle[1] - l_knee[1])]
|
85 |
+
l_knee_hip = [l_hip[0] - l_knee[0], 0-(l_hip[1] - l_knee[1])]
|
86 |
+
angle = find_angle(l_knee_ankle, l_knee_hip)
|
87 |
+
angles.append(angle)
|
88 |
+
# print(angle)
|
89 |
+
if angle < 70:
|
90 |
+
three_in_a_row += 1
|
91 |
+
if three_in_a_row >=3:
|
92 |
+
return 'tuck'
|
93 |
+
else:
|
94 |
+
three_in_a_row =0
|
95 |
+
if twist_counter_full_dive(dive_data) > 0 and som_counter_full_dive(dive_data)[0] < 5:
|
96 |
+
return 'free'
|
97 |
+
return 'pike'
|
98 |
+
|
99 |
+
|
100 |
+
def distance_point_to_line_segment(px, py, x1, y1, x2, y2):
|
101 |
+
# Calculate the squared distance from point (px, py) to the line segment [(x1, y1), (x2, y2)]
|
102 |
+
def sqr_distance_point_to_segment():
|
103 |
+
line_length_sq = (x2 - x1)**2 + (y2 - y1)**2
|
104 |
+
if line_length_sq == 0:
|
105 |
+
return (px - x1)**2 + (py - y1)**2
|
106 |
+
t = max(0, min(1, ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / line_length_sq))
|
107 |
+
return ((px - (x1 + t * (x2 - x1)))**2 + (py - (y1 + t * (y2 - y1)))**2)
|
108 |
+
|
109 |
+
# Calculate the closest point on the line segment to the given point (px, py)
|
110 |
+
def closest_point_on_line_segment():
|
111 |
+
line_length_sq = (x2 - x1)**2 + (y2 - y1)**2
|
112 |
+
if line_length_sq == 0:
|
113 |
+
return x1, y1
|
114 |
+
t = max(0, min(1, ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / line_length_sq))
|
115 |
+
closest_x = x1 + t * (x2 - x1)
|
116 |
+
closest_y = y1 + t * (y2 - y1)
|
117 |
+
return closest_x, closest_y
|
118 |
+
|
119 |
+
closest_point = closest_point_on_line_segment()
|
120 |
+
distance = math.sqrt(sqr_distance_point_to_segment())
|
121 |
+
|
122 |
+
return closest_point, distance
|
123 |
+
|
124 |
+
def min_distance_from_line_to_circle(line_start, line_end, circle_center, circle_radius):
|
125 |
+
closest_point, distance = distance_point_to_line_segment(circle_center[0], circle_center[1],
|
126 |
+
line_start[0], line_start[1],
|
127 |
+
line_end[0], line_end[1])
|
128 |
+
|
129 |
+
min_distance = max(0, distance - circle_radius)
|
130 |
+
return min_distance
|
131 |
+
|
132 |
+
|
133 |
+
def twister(pose_pred, prev_pose_pred=None, in_petal=False, petal_count=0, outer=10, inner=9, valid=17, middle=0.5):
|
134 |
+
if pose_pred is None:
|
135 |
+
return petal_count, in_petal
|
136 |
+
min_dist = 0
|
137 |
+
# Users/lokamoto/Comprehensive_AQA/output/joint_plots/FINAWorldChampionships2019_Women10m_final_r1_0
|
138 |
+
pose_pred = pose_pred[0]
|
139 |
+
vector1 = [pose_pred[2][0] - pose_pred[3][0], 0-(pose_pred[2][1] - pose_pred[3][1])]
|
140 |
+
if prev_pose_pred is not None:
|
141 |
+
prev_pose_pred = prev_pose_pred[0]
|
142 |
+
prev_pose_pred = [prev_pose_pred[2][0] - prev_pose_pred[3][0], 0-(prev_pose_pred[2][1] - prev_pose_pred[3][1])]
|
143 |
+
min_dist = min_distance_from_line_to_circle(prev_pose_pred, vector1, (0, 0), middle)
|
144 |
+
if np.linalg.norm(vector1) > valid:
|
145 |
+
return petal_count, in_petal
|
146 |
+
if min_dist is not None and in_petal and np.linalg.norm(vector1) > outer and min_dist == 0: #and np.linalg.norm(vector1) > 8
|
147 |
+
petal_count += 1
|
148 |
+
# print('leaving petal')
|
149 |
+
# print('going in new petal')
|
150 |
+
elif not in_petal and np.linalg.norm(vector1) > outer: #and min_dist > 3: #and np.linalg.norm(vector1) > 8
|
151 |
+
in_petal = True
|
152 |
+
petal_count += 1
|
153 |
+
# print('going in petal')
|
154 |
+
elif in_petal and np.linalg.norm(vector1) < inner:
|
155 |
+
in_petal = False
|
156 |
+
|
157 |
+
# print('leaving petal')
|
158 |
+
# print(vector)
|
159 |
+
return petal_count, in_petal
|
160 |
+
|
161 |
+
|
162 |
+
def twist_counter_full_dive(dive_data, visualize=False):
|
163 |
+
twists_gt = []
|
164 |
+
twists_gt.extend(range(29, 36))
|
165 |
+
twists_gt.extend([41, 42])
|
166 |
+
start = [1, 2, 3, 4, 5, 6, 7]
|
167 |
+
# key = ('01',17)
|
168 |
+
# print(ground_truth[key][0])
|
169 |
+
# print(dive_data['twist_counts'])
|
170 |
+
dist_hip = []
|
171 |
+
prev_pose_pred = None
|
172 |
+
in_petal=False
|
173 |
+
petal_count=0
|
174 |
+
scale = get_scale_factor(dive_data)
|
175 |
+
valid = scale / 1.5
|
176 |
+
outer = scale / 3.2
|
177 |
+
inner = scale / 3.4
|
178 |
+
middle = 0.5
|
179 |
+
next_next_pose_pred = dive_data['pose_pred'][4]
|
180 |
+
# bad_poses = invalid_poses(key)
|
181 |
+
for i in range(len(dive_data['pose_pred'])):
|
182 |
+
# if ground_truth[key][4][i] not in twists_gt:
|
183 |
+
# continue
|
184 |
+
# if i in bad_poses:
|
185 |
+
# continue
|
186 |
+
pose_pred = dive_data['pose_pred'][i]
|
187 |
+
if i < len(dive_data['pose_pred']) - 1:
|
188 |
+
next_pose_pred = dive_data['pose_pred'][i + 1]
|
189 |
+
if i < len(dive_data['pose_pred']) - 4 and next_next_pose_pred is not None:
|
190 |
+
next_next_pose_pred = dive_data['pose_pred'][i + 4]
|
191 |
+
if pose_pred is None or dive_data['on_boards'][i] == 1 or dive_data['position_tightness'][i] <= 80 or next_next_pose_pred is None:
|
192 |
+
continue
|
193 |
+
petal_count, in_petal = twister(pose_pred, prev_pose_pred=prev_pose_pred, in_petal=in_petal, petal_count=petal_count, outer=outer, inner=inner, middle=middle, valid=valid)
|
194 |
+
prev_pose_pred = pose_pred
|
195 |
+
# print(petal_count)
|
196 |
+
if visualize:
|
197 |
+
pose_pred = pose_pred[0]
|
198 |
+
dist_hip.append([pose_pred[2][0] - pose_pred[3][0], 0-(pose_pred[2][1] - pose_pred[3][1])])
|
199 |
+
if visualize:
|
200 |
+
dist_hip = np.array(dist_hip)
|
201 |
+
plt.plot(dist_hip[:, 0], dist_hip[:, 1], label="right-to-left hip")
|
202 |
+
circle1 = plt.Circle((0, 0), outer, fill=False)
|
203 |
+
plt.gca().add_patch(circle1)
|
204 |
+
circle2 = plt.Circle((0, 0), inner, fill=False)
|
205 |
+
plt.gca().add_patch(circle2)
|
206 |
+
circle3 = plt.Circle((0, 0), valid, fill=False)
|
207 |
+
plt.gca().add_patch(circle3)
|
208 |
+
plt.legend()
|
209 |
+
plt.show()
|
210 |
+
return petal_count
|
211 |
+
|
212 |
+
def rotation_direction_som(vector1, vector2, threshold=0.4):
|
213 |
+
# Calculate the determinant to determine rotation direction
|
214 |
+
determinant = vector1[0] * vector2[1] - vector1[1] * vector2[0]
|
215 |
+
mag1= np.linalg.norm(vector1)
|
216 |
+
mag2= np.linalg.norm(vector2)
|
217 |
+
norm_det = determinant/(mag1*mag2)
|
218 |
+
theta = np.arcsin(norm_det)
|
219 |
+
return math.degrees(theta)
|
220 |
+
|
221 |
+
def is_handstand(dive_data):
|
222 |
+
first_frame_pose_pred = dive_data['pose_pred'][0]
|
223 |
+
handstand = False
|
224 |
+
if first_frame_pose_pred[0][6][1] < first_frame_pose_pred[0][7][1]:
|
225 |
+
handstand = True
|
226 |
+
return handstand
|
227 |
+
|
228 |
+
def som_counter_full_dive(dive_data, visualize=False):
|
229 |
+
start = [1, 2, 3, 4, 5, 6, 7]
|
230 |
+
entry = [36]
|
231 |
+
half_som_count = 0
|
232 |
+
# key = ('04', 47)
|
233 |
+
# print(ground_truth[key][0])
|
234 |
+
dist_body = []
|
235 |
+
handstand = is_handstand(dive_data)
|
236 |
+
# key = ('04',42)
|
237 |
+
next_next_pose_pred = dive_data['pose_pred'][2]
|
238 |
+
# bad_poses = invalid_poses(key)
|
239 |
+
prev = None
|
240 |
+
for i in range(len(dive_data['pose_pred'])):
|
241 |
+
# if i in bad_poses:
|
242 |
+
# continue
|
243 |
+
pose_pred = dive_data['pose_pred'][i]
|
244 |
+
if i < len(dive_data['pose_pred']) - 2 and next_next_pose_pred is not None:
|
245 |
+
next_next_pose_pred = dive_data['pose_pred'][i + 2]
|
246 |
+
if pose_pred is None or next_next_pose_pred is None or dive_data['on_boards'][i] == 1: # ground_truth[key][4][i] in start:
|
247 |
+
continue
|
248 |
+
|
249 |
+
pose_pred = pose_pred[0]
|
250 |
+
vector1 = [pose_pred[7][0] - pose_pred[6][0], 0-(pose_pred[7][1] - pose_pred[6][1])] # flip y axis
|
251 |
+
if (not handstand and half_som_count % 2 == 0) or (handstand and half_som_count % 2 == 1):
|
252 |
+
vector2 = [0, -1]
|
253 |
+
else:
|
254 |
+
vector2 = [0, 1]
|
255 |
+
sensitivity = 115
|
256 |
+
if prev is not None and find_angle(vector1, prev) > sensitivity:
|
257 |
+
continue
|
258 |
+
is_clockwise = is_rotating_clockwise(dive_data)
|
259 |
+
if prev is not None and ((is_clockwise and rotation_direction_som(vector1, prev)<0) or (not is_clockwise and rotation_direction_som(vector1, prev)>0)):
|
260 |
+
continue
|
261 |
+
angle = find_angle(vector1, vector2)
|
262 |
+
# print("unit_vector_1:", unit_vector_1)
|
263 |
+
# print("looking for vector:", vector2)
|
264 |
+
# print(half_som_count)
|
265 |
+
# print(angle)
|
266 |
+
if angle <= 75:
|
267 |
+
half_som_count += 1
|
268 |
+
if visualize:
|
269 |
+
dist_body.append([pose_pred[7][0] - pose_pred[6][0], 0-(pose_pred[7][1] - pose_pred[6][1])])
|
270 |
+
prev = vector1
|
271 |
+
|
272 |
+
if visualize:
|
273 |
+
dist_body = np.array(dist_body)
|
274 |
+
plt.plot(dist_body[:, 0], dist_body[:, 1], label="pelvis-to-thorax")
|
275 |
+
plt.xlabel("x-coord")
|
276 |
+
plt.ylabel("y-coord")
|
277 |
+
|
278 |
+
plt.legend()
|
279 |
+
plt.show()
|
280 |
+
return half_som_count, handstand
|
281 |
+
|
282 |
+
def getDiveInfo(diveNum):
|
283 |
+
handstand = (diveNum[0] == '6')
|
284 |
+
expected_som = int(diveNum[2])
|
285 |
+
if len(diveNum) == 5:
|
286 |
+
expected_twists = int(diveNum[3])
|
287 |
+
else:
|
288 |
+
expected_twists = 0
|
289 |
+
if diveNum[0] == '1' or diveNum[0] == '3' or diveNum[:2] == '51' or diveNum[:2] == '53' or diveNum[:2] == '61' or diveNum[:2] == '63':
|
290 |
+
back_facing = False
|
291 |
+
else:
|
292 |
+
back_facing = True
|
293 |
+
if diveNum[0] == '1' or diveNum[:2] == '51' or diveNum[:2] == '61':
|
294 |
+
expected_direction = 'front'
|
295 |
+
elif diveNum[0] == '2' or diveNum[:2] == '52' or diveNum[:2] == '62':
|
296 |
+
expected_direction = 'back'
|
297 |
+
elif diveNum[0] == '3' or diveNum[:2] == '53' or diveNum[:2] == '63':
|
298 |
+
expected_direction = 'reverse'
|
299 |
+
elif diveNum[0] == '4':
|
300 |
+
expected_direction = 'inward'
|
301 |
+
if diveNum[-1] == 'b':
|
302 |
+
position = 'pike'
|
303 |
+
elif diveNum[-1] == 'c':
|
304 |
+
position = 'tuck'
|
305 |
+
else:
|
306 |
+
position = 'free'
|
307 |
+
return handstand, expected_som, expected_twists, back_facing, expected_direction, position
|
308 |
+
|
309 |
+
def get_direction(dive_data):
|
310 |
+
clockwise = is_rotating_clockwise(dive_data)
|
311 |
+
board_side = dive_data['board_side']
|
312 |
+
if board_side == "right":
|
313 |
+
back_facing = is_back_facing(dive_data, 'right')
|
314 |
+
if back_facing and clockwise:
|
315 |
+
direction = 'inward'
|
316 |
+
elif back_facing and not clockwise:
|
317 |
+
direction = 'back'
|
318 |
+
elif not back_facing and clockwise:
|
319 |
+
direction = 'reverse'
|
320 |
+
elif not back_facing and not clockwise:
|
321 |
+
direction = 'front'
|
322 |
+
else:
|
323 |
+
back_facing = is_back_facing(dive_data, 'left')
|
324 |
+
if back_facing and clockwise:
|
325 |
+
direction = 'back'
|
326 |
+
elif back_facing and not clockwise:
|
327 |
+
direction = 'inward'
|
328 |
+
elif not back_facing and clockwise:
|
329 |
+
direction = 'front'
|
330 |
+
elif not back_facing and not clockwise:
|
331 |
+
direction = 'reverse'
|
332 |
+
return direction
|
333 |
+
|
334 |
+
def is_rotating_clockwise(dive_data):
|
335 |
+
directions = []
|
336 |
+
for i in range(1, len(dive_data['pose_pred'])):
|
337 |
+
if dive_data['pose_pred'][i] is None or dive_data['pose_pred'][i-1] is None:
|
338 |
+
continue
|
339 |
+
if dive_data['on_boards'][i] == 0:
|
340 |
+
prev_pose_pred_hip = dive_data['pose_pred'][i-1][0][3]
|
341 |
+
curr_pose_pred_hip = dive_data['pose_pred'][i][0][3]
|
342 |
+
prev_pose_pred_knee = dive_data['pose_pred'][i-1][0][4]
|
343 |
+
curr_pose_pred_knee = dive_data['pose_pred'][i][0][4]
|
344 |
+
prev_hip_knee = [prev_pose_pred_knee[0] - prev_pose_pred_hip[0], 0-(prev_pose_pred_knee[1] - prev_pose_pred_hip[1])]
|
345 |
+
curr_hip_knee = [curr_pose_pred_knee[0] - curr_pose_pred_hip[0], 0-(curr_pose_pred_knee[1] - curr_pose_pred_hip[1])]
|
346 |
+
direction = rotation_direction(prev_hip_knee, curr_hip_knee, threshold=0)
|
347 |
+
directions.append(direction)
|
348 |
+
return np.sum(directions) < 0
|
349 |
+
|
350 |
+
|
351 |
+
|
generate_reports.py
ADDED
@@ -0,0 +1,551 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from jinja2 import Environment, FileSystemLoader
|
2 |
+
import pickle
|
3 |
+
import os
|
4 |
+
import numpy as np
|
5 |
+
from PIL import Image, ImageDraw
|
6 |
+
from io import BytesIO
|
7 |
+
import cv2
|
8 |
+
import base64
|
9 |
+
from pathlib import Path
|
10 |
+
import torch
|
11 |
+
import gradio as gr
|
12 |
+
|
13 |
+
############ Generate GIF functions ###################################################################################
|
14 |
+
def generate_gif(local_directory, image_names, speed_factor=1, loop=0):
|
15 |
+
"""
|
16 |
+
Generate a GIF from a sequence of images paths saved in a local directory.
|
17 |
+
|
18 |
+
Parameters:
|
19 |
+
- local_directory (str): Directory path where the images are located
|
20 |
+
- image_paths (list): List of filenames of the input images.
|
21 |
+
- speed_factor (int): How fast the GIF is, the higher the less the delay is between frames
|
22 |
+
- loop (int): Number of loops (0 for infinite loop).
|
23 |
+
|
24 |
+
Returns:
|
25 |
+
- Bytes of GIF
|
26 |
+
"""
|
27 |
+
images = []
|
28 |
+
durations = []
|
29 |
+
for image_name in image_names:
|
30 |
+
img = Image.open(os.path.join(local_directory, image_name))
|
31 |
+
images.append(img)
|
32 |
+
try:
|
33 |
+
duration = img.info['duration']
|
34 |
+
except KeyError:
|
35 |
+
duration = 100 # Default duration in case 'duration' is not available
|
36 |
+
durations.append(duration)
|
37 |
+
|
38 |
+
# Calculate the adjusted durations based on the speed factor
|
39 |
+
adjusted_durations = [int(duration / speed_factor) for duration in durations]
|
40 |
+
|
41 |
+
# Save as GIF to an in-memory buffer
|
42 |
+
gif_buffer = BytesIO()
|
43 |
+
images[0].save(gif_buffer, format='GIF', save_all=True, append_images=images[1:], duration=adjusted_durations, loop=loop)
|
44 |
+
|
45 |
+
# Get the content of the buffer as bytes
|
46 |
+
gif_content = gif_buffer.getvalue()
|
47 |
+
gif_content = base64.b64encode(gif_content).decode('utf-8')
|
48 |
+
return gif_content
|
49 |
+
|
50 |
+
def generate_gif_from_frames(frames, speed_factor=1, loop=0, progress=gr.Progress()):
|
51 |
+
"""
|
52 |
+
Generate a GIF from a sequence of images.
|
53 |
+
|
54 |
+
Parameters:
|
55 |
+
- frames (list): List of cv2 frames
|
56 |
+
- speed_factor (int): How fast the GIF is, the higher the less the delay is between frames
|
57 |
+
- loop (int): Number of loops (0 for infinite loop).
|
58 |
+
|
59 |
+
Returns:
|
60 |
+
- Bytes of GIF
|
61 |
+
"""
|
62 |
+
durations = []
|
63 |
+
images = []
|
64 |
+
i = 0
|
65 |
+
for frame in frames:
|
66 |
+
# progress((len(frames)+i)/(2*len(frames)), desc="Abstracting Symbols")
|
67 |
+
image = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
|
68 |
+
images.append(image)
|
69 |
+
duration = 100 # Default duration in case 'duration' is not available
|
70 |
+
durations.append(duration)
|
71 |
+
i+=1
|
72 |
+
|
73 |
+
# Calculate the adjusted durations based on the speed factor
|
74 |
+
adjusted_durations = [int(duration / speed_factor) for duration in durations]
|
75 |
+
|
76 |
+
# images[0].save('test.gif',
|
77 |
+
# save_all = True, append_images = images[1:],
|
78 |
+
# optimize = False, duration =adjusted_durations, loop=loop)
|
79 |
+
|
80 |
+
# Save as GIF to an in-memory buffer
|
81 |
+
gif_buffer = BytesIO()
|
82 |
+
images[0].save(gif_buffer, format='GIF', save_all=True, append_images=images[1:], duration=adjusted_durations, loop=loop)
|
83 |
+
|
84 |
+
# Get the content of the buffer as bytes
|
85 |
+
gif_content = gif_buffer.getvalue()
|
86 |
+
gif_content = base64.b64encode(gif_content).decode('utf-8')
|
87 |
+
return gif_content
|
88 |
+
|
89 |
+
##########################################################################################################
|
90 |
+
############ Overlay Symbols on Frames ######################################################################
|
91 |
+
SKELETON = [
|
92 |
+
[1,2],[1,0],[2,6],[3,6],[4,5],[3,4],[6,7],[7,8],[9,8],[7,12],[7,13],[11,12],[13,14],[14,15],[10,11]
|
93 |
+
]
|
94 |
+
CocoColors = [[255, 0, 0], [255, 85, 0], [255, 170, 0], [255, 255, 0], [170, 255, 0], [85, 255, 0], [0, 255, 0],
|
95 |
+
[0, 255, 85], [0, 255, 170], [0, 255, 255], [0, 170, 255], [0, 85, 255], [0, 0, 255], [85, 0, 255],
|
96 |
+
[170, 0, 255], [255, 0, 255], [255, 0, 170], [255, 0, 85]]
|
97 |
+
NUM_KPTS = 16
|
98 |
+
def draw_pose(keypoints,img, board_end_coord):
|
99 |
+
"""draw the keypoints and the skeletons.
|
100 |
+
:params keypoints: the shape should be equal to [17,2]
|
101 |
+
:params img:
|
102 |
+
"""
|
103 |
+
assert keypoints.shape == (NUM_KPTS,2)
|
104 |
+
for i in range(len(SKELETON)):
|
105 |
+
kpt_a, kpt_b = SKELETON[i][0], SKELETON[i][1]
|
106 |
+
x_a, y_a = keypoints[kpt_a][0],keypoints[kpt_a][1]
|
107 |
+
x_b, y_b = keypoints[kpt_b][0],keypoints[kpt_b][1]
|
108 |
+
cv2.circle(img, (int(x_a), int(y_a)), 6, CocoColors[i], -1)
|
109 |
+
cv2.circle(img, (int(x_b), int(y_b)), 6, CocoColors[i], -1)
|
110 |
+
cv2.line(img, (int(x_a), int(y_a)), (int(x_b), int(y_b)), CocoColors[i], 2)
|
111 |
+
# cv2.circle(img, board_end_coord, 4, [0, 0, 0], -1)
|
112 |
+
|
113 |
+
def draw_symbols(opencv_image, pose_preds, board_end_coord, plat_outputs, splash_pred_mask, above_board=None):
|
114 |
+
# Open image using openCV2
|
115 |
+
# opencv_image = cv2.imread(image_path)
|
116 |
+
if pose_preds is not None:
|
117 |
+
draw_pose(np.array(pose_preds)[0],opencv_image, board_end_coord)
|
118 |
+
if above_board is None or above_board==1:
|
119 |
+
draw_platform(opencv_image, plat_outputs)
|
120 |
+
draw_splash(opencv_image, splash_pred_mask)
|
121 |
+
# # Notice the COLOR_BGR2RGB which means that the color is
|
122 |
+
# # converted from BGR to RGB
|
123 |
+
# color_converted = cv2.cvtColor(opencv_image, cv2.COLOR_BGR2RGB)
|
124 |
+
|
125 |
+
# # Displaying the converted image
|
126 |
+
# pil_image = Image.fromarray(color_converted)
|
127 |
+
return opencv_image
|
128 |
+
|
129 |
+
def draw_platform(opencv_image, output):
|
130 |
+
pred_classes = output['instances'].pred_classes.cpu().numpy()
|
131 |
+
platforms = np.where(pred_classes == 0)[0]
|
132 |
+
scores = output['instances'].scores[platforms]
|
133 |
+
if len(scores) == 0:
|
134 |
+
return
|
135 |
+
pred_masks = output['instances'].pred_masks[platforms]
|
136 |
+
max_instance = torch.argmax(scores)
|
137 |
+
pred_mask = np.array(pred_masks[max_instance].cpu())
|
138 |
+
# Convert the mask to a binary image
|
139 |
+
binary_mask = pred_mask.squeeze().astype(np.uint8)
|
140 |
+
contours, hierarchy = cv2.findContours(binary_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
|
141 |
+
|
142 |
+
cv2.drawContours(opencv_image, contours[0], -1, (36, 255, 12), thickness=5)
|
143 |
+
|
144 |
+
def draw_splash(opencv_image, pred_mask):
|
145 |
+
# Convert the mask to a binary image
|
146 |
+
if pred_mask is None:
|
147 |
+
return
|
148 |
+
binary_mask = pred_mask.squeeze().astype(np.uint8)
|
149 |
+
contours, hierarchy = cv2.findContours(binary_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
|
150 |
+
|
151 |
+
cv2.drawContours(opencv_image, contours[0], -1, (0, 0, 0), thickness=5)
|
152 |
+
|
153 |
+
##########################################################################################################
|
154 |
+
############ Generate HTML template ######################################################################
|
155 |
+
|
156 |
+
def generate_report(template_path, data, directory, local_directory, progress=gr.Progress()):
|
157 |
+
# Load the template environment
|
158 |
+
env = Environment(loader=FileSystemLoader('.'))
|
159 |
+
|
160 |
+
file_names = os.listdir(local_directory)
|
161 |
+
file_names.sort()
|
162 |
+
file_names = np.array(file_names)
|
163 |
+
progress(0.9, desc="Generating Score Report")
|
164 |
+
# Load the template
|
165 |
+
is_twister = data['twist_position_tightness']['raw_score'] is not None
|
166 |
+
overall_score_desc = data['overall_score']['description']
|
167 |
+
overall_score = '%.1f' % data['overall_score']['raw_score']
|
168 |
+
|
169 |
+
feet_apart_score = round(float('%.2f' % data['feet_apart']['raw_score']))
|
170 |
+
feet_apart_peaks = file_names[data['feet_apart']['peaks']]
|
171 |
+
feet_apart_gif = None
|
172 |
+
has_feet_apart_peaks = False
|
173 |
+
if len(feet_apart_peaks) > 0:
|
174 |
+
has_feet_apart_peaks = True
|
175 |
+
feet_apart_gif = generate_gif(local_directory, feet_apart_peaks, speed_factor = 0.05)
|
176 |
+
feet_apart_percentile = round(float('%.2f' % (data['feet_apart']['percentile'] *100)))
|
177 |
+
feet_apart_percentile_divided_by_ten = '%.1f' % (data['feet_apart']['percentile'] *10)
|
178 |
+
|
179 |
+
include_height_off_platform = False
|
180 |
+
height_off_board_score = data['height_off_board']['raw_score']
|
181 |
+
height_off_board_percentile = data['height_off_board']['percentile']
|
182 |
+
height_off_board_description = None
|
183 |
+
height_off_board_percentile_divided_by_ten = None
|
184 |
+
encoded_height_off_board_frame = None
|
185 |
+
if height_off_board_score is not None:
|
186 |
+
include_height_off_platform = True
|
187 |
+
height_off_board_score = round(float('%.2f' % data['height_off_board']['raw_score']))
|
188 |
+
height_off_board_frame = file_names[data['height_off_board']['frame_index']]
|
189 |
+
height_off_board_frame_path = os.path.join(local_directory, height_off_board_frame)
|
190 |
+
with open(height_off_board_frame_path, "rb") as image_file:
|
191 |
+
encoded_height_off_board_frame = base64.b64encode(image_file.read()).decode('utf-8')
|
192 |
+
height_off_board_percentile = round(float('%.2f' % (data['height_off_board']['percentile'] *100)))
|
193 |
+
height_off_board_percentile_divided_by_ten = '%.1f' % (data['height_off_board']['percentile'] *10)
|
194 |
+
if float(height_off_board_percentile_divided_by_ten) > 5:
|
195 |
+
height_off_board_description = "good"
|
196 |
+
else:
|
197 |
+
height_off_board_description = "a bit on the lower side"
|
198 |
+
|
199 |
+
dist_from_board_score = '%.2f' % data['distance_from_board']['raw_score']
|
200 |
+
dist_from_board_frame = file_names[data['distance_from_board']['frame_index']]
|
201 |
+
dist_from_board_frame_path = os.path.join(local_directory, dist_from_board_frame)
|
202 |
+
with open(dist_from_board_frame_path, "rb") as image_file:
|
203 |
+
encoded_dist_from_board_frame = base64.b64encode(image_file.read()).decode('utf-8')
|
204 |
+
dist_from_board_percentile = data['distance_from_board']['percentile']
|
205 |
+
if 'good' in dist_from_board_percentile:
|
206 |
+
dist_from_board_percentile_status = "Good"
|
207 |
+
elif 'far' in dist_from_board_percentile:
|
208 |
+
dist_from_board_percentile_status = "Too Far"
|
209 |
+
else:
|
210 |
+
dist_from_board_percentile_status = "Too Close"
|
211 |
+
|
212 |
+
knee_bend_score = data['knee_bend']['raw_score']
|
213 |
+
knee_bend_percentile = data['knee_bend']['percentile']
|
214 |
+
knee_bend_frames = []
|
215 |
+
knee_bend_percentile_divided_by_ten = None
|
216 |
+
if knee_bend_score is not None:
|
217 |
+
knee_bend_score = round(float('%.2f' % (data['knee_bend']['raw_score'])))
|
218 |
+
knee_bend_frames = file_names[data['knee_bend']['frame_indices']]
|
219 |
+
knee_bend_percentile = round(float('%.2f' % (knee_bend_percentile * 100)))
|
220 |
+
knee_bend_percentile_divided_by_ten = '%.1f' % (data['knee_bend']['percentile'] * 10)
|
221 |
+
|
222 |
+
som_position_tightness_score = data['som_position_tightness']['raw_score']
|
223 |
+
som_position_tightness_percentile = data['som_position_tightness']['percentile']
|
224 |
+
som_position_tightness_position = data['som_position_tightness']['position']
|
225 |
+
som_position_tightness_frames = file_names[data['som_position_tightness']['frame_indices']]
|
226 |
+
som_position_tightness_gif = None
|
227 |
+
som_position_tightness_percentile_divided_by_ten = None
|
228 |
+
if som_position_tightness_score is not None:
|
229 |
+
if is_twister:
|
230 |
+
som_position_tightness_score = round(float('%.2f' % (data['som_position_tightness']['raw_score'] + 15)))
|
231 |
+
else:
|
232 |
+
som_position_tightness_score = round(float('%.2f' % (data['som_position_tightness']['raw_score'])))
|
233 |
+
som_position_tightness_gif = generate_gif(local_directory, som_position_tightness_frames)
|
234 |
+
som_position_tightness_percentile = round(float('%.2f' % (som_position_tightness_percentile * 100)))
|
235 |
+
som_position_tightness_percentile_divided_by_ten = '%.1f' % (data['som_position_tightness']['percentile'] * 10)
|
236 |
+
twist_position_tightness_score = data['twist_position_tightness']['raw_score']
|
237 |
+
twist_position_tightness_frames = []
|
238 |
+
twist_position_tightness_gif = None
|
239 |
+
twist_position_tightness_percentile = None
|
240 |
+
twist_position_tightness_percentile_divided_by_ten = None
|
241 |
+
if twist_position_tightness_score is not None:
|
242 |
+
twist_position_tightness_score = round(float('%.2f' % twist_position_tightness_score))
|
243 |
+
twist_position_tightness_frames = file_names[data['twist_position_tightness']['frame_indices']]
|
244 |
+
twist_position_tightness_gif = generate_gif(local_directory, twist_position_tightness_frames)
|
245 |
+
twist_position_tightness_percentile = round(float('%.2f' % (data['twist_position_tightness']['percentile'] * 100)))
|
246 |
+
twist_position_tightness_percentile_divided_by_ten = '%.1f' % (data['twist_position_tightness']['percentile'] * 10)
|
247 |
+
over_under_rotation_score = round(float('%.2f' % data['over_under_rotation']['raw_score']))
|
248 |
+
over_under_rotation_frame = file_names[data['over_under_rotation']['frame_index']]
|
249 |
+
over_under_rotation_percentile = round(float('%.2f' % (data['over_under_rotation']['percentile'] * 100)))
|
250 |
+
over_under_rotation_percentile_divided_by_ten = '%.1f' % (data['over_under_rotation']['percentile'] * 10)
|
251 |
+
straightness_during_entry_score = round(float('%.2f' % data['straightness_during_entry']['raw_score']))
|
252 |
+
straightness_during_entry_frames = file_names[data['straightness_during_entry']['frame_indices']]
|
253 |
+
straightness_during_entry_gif = generate_gif(local_directory, straightness_during_entry_frames, speed_factor = 0.5)
|
254 |
+
straightness_during_entry_percentile = round(float('%.2f' % (data['straightness_during_entry']['percentile'] * 100)))
|
255 |
+
straightness_during_entry_percentile_divided_by_ten = '%.1f' % (data['straightness_during_entry']['percentile'] * 10)
|
256 |
+
splash_score = round(float('%.2f' % data['splash']['raw_score']))
|
257 |
+
splash_frame = file_names[data['splash']['maximum_index']]
|
258 |
+
splash_indices = file_names[data['splash']['frame_indices']]
|
259 |
+
splash_gif = None
|
260 |
+
if len(splash_indices) > 0:
|
261 |
+
splash_gif = generate_gif(local_directory, splash_indices)
|
262 |
+
splash_percentile = round(float('%.2f' % (data['splash']['percentile'] * 100)))
|
263 |
+
splash_percentile_divided_by_ten = '%.1f' % (data['splash']['percentile'] * 10)
|
264 |
+
if float(splash_percentile) < 50:
|
265 |
+
splash_description = 'on the larger side'
|
266 |
+
else:
|
267 |
+
splash_description = 'small'
|
268 |
+
template = env.get_template(template_path)
|
269 |
+
data = {
|
270 |
+
'directory' : directory,
|
271 |
+
'local_directory': local_directory,
|
272 |
+
'is_twister' : is_twister,
|
273 |
+
'overall_score_desc' : overall_score_desc,
|
274 |
+
'overall_score' : overall_score,
|
275 |
+
'feet_apart_score' : feet_apart_score,
|
276 |
+
'feet_apart_peaks' : feet_apart_peaks,
|
277 |
+
'has_feet_apart_peaks' : has_feet_apart_peaks,
|
278 |
+
'feet_apart_gif' : feet_apart_gif,
|
279 |
+
'feet_apart_percentile' : feet_apart_percentile,
|
280 |
+
'feet_apart_percentile_divided_by_ten': feet_apart_percentile_divided_by_ten,
|
281 |
+
|
282 |
+
'include_height_off_platform': include_height_off_platform,
|
283 |
+
'height_off_board_score' : height_off_board_score,
|
284 |
+
'height_off_board_percentile' : height_off_board_percentile,
|
285 |
+
'encoded_height_off_board_frame' : encoded_height_off_board_frame,
|
286 |
+
'height_off_board_percentile_divided_by_ten': height_off_board_percentile_divided_by_ten,
|
287 |
+
'height_off_board_description' : height_off_board_description,
|
288 |
+
|
289 |
+
'dist_from_board_score' : dist_from_board_score,
|
290 |
+
'dist_from_board_frame' : dist_from_board_frame,
|
291 |
+
'encoded_dist_from_board_frame': encoded_dist_from_board_frame,
|
292 |
+
'dist_from_board_percentile' : dist_from_board_percentile,
|
293 |
+
'dist_from_board_percentile_status': dist_from_board_percentile_status,
|
294 |
+
|
295 |
+
'knee_bend_score' : knee_bend_score,
|
296 |
+
'knee_bend_frames' : knee_bend_frames,
|
297 |
+
'knee_bend_percentile' : knee_bend_percentile,
|
298 |
+
'knee_bend_percentile_divided_by_ten' : knee_bend_percentile_divided_by_ten,
|
299 |
+
|
300 |
+
'som_position_tightness_score' : som_position_tightness_score,
|
301 |
+
'som_position_tightness_frames' : som_position_tightness_frames,
|
302 |
+
'som_position_tightness_gif' : som_position_tightness_gif,
|
303 |
+
'som_position_tightness_position' : som_position_tightness_position,
|
304 |
+
'som_position_tightness_percentile' : som_position_tightness_percentile,
|
305 |
+
'som_position_tightness_percentile_divided_by_ten' : som_position_tightness_percentile_divided_by_ten,
|
306 |
+
'twist_position_tightness_score' : twist_position_tightness_score,
|
307 |
+
'twist_position_tightness_frames': twist_position_tightness_frames,
|
308 |
+
'twist_position_tightness_percentile' : twist_position_tightness_percentile,
|
309 |
+
'twist_position_tightness_percentile_divided_by_ten' : twist_position_tightness_percentile_divided_by_ten,
|
310 |
+
'twist_position_tightness_gif' : twist_position_tightness_gif,
|
311 |
+
'over_under_rotation_score' : over_under_rotation_score,
|
312 |
+
'over_under_rotation_frame' : over_under_rotation_frame,
|
313 |
+
'over_under_rotation_percentile' : over_under_rotation_percentile,
|
314 |
+
'over_under_rotation_percentile_divided_by_ten' : over_under_rotation_percentile_divided_by_ten,
|
315 |
+
'straightness_during_entry_score' : straightness_during_entry_score,
|
316 |
+
'straightness_during_entry_gif' : straightness_during_entry_gif,
|
317 |
+
'straightness_during_entry_percentile' : straightness_during_entry_percentile,
|
318 |
+
'straightness_during_entry_percentile_divided_by_ten': straightness_during_entry_percentile_divided_by_ten,
|
319 |
+
'splash_score' : splash_score,
|
320 |
+
'splash_frame' : splash_frame,
|
321 |
+
'splash_gif' : splash_gif,
|
322 |
+
'splash_percentile' : splash_percentile,
|
323 |
+
'splash_percentile_divided_by_ten': splash_percentile_divided_by_ten,
|
324 |
+
'splash_description' : splash_description,
|
325 |
+
}
|
326 |
+
# Render the template with the provided data
|
327 |
+
report_content = template.render(data)
|
328 |
+
return report_content
|
329 |
+
|
330 |
+
|
331 |
+
def generate_report_from_frames(template_path, data, frames):
|
332 |
+
# Load the template environment
|
333 |
+
env = Environment(loader=FileSystemLoader('.'))
|
334 |
+
|
335 |
+
frames = np.array(frames)
|
336 |
+
# Load the template
|
337 |
+
is_twister = data['twist_position_tightness']['raw_score'] is not None
|
338 |
+
overall_score_desc = data['overall_score']['description']
|
339 |
+
overall_score = '%.1f' % data['overall_score']['raw_score']
|
340 |
+
|
341 |
+
feet_apart_score = round(float('%.2f' % data['feet_apart']['raw_score']))
|
342 |
+
feet_apart_peaks = frames[data['feet_apart']['peaks']]
|
343 |
+
feet_apart_gif = None
|
344 |
+
has_feet_apart_peaks = False
|
345 |
+
if len(feet_apart_peaks) > 0:
|
346 |
+
has_feet_apart_peaks = True
|
347 |
+
feet_apart_gif = generate_gif_from_frames(feet_apart_peaks, speed_factor = 0.05)
|
348 |
+
feet_apart_percentile = round(float('%.2f' % (data['feet_apart']['percentile'] *100)))
|
349 |
+
feet_apart_percentile_divided_by_ten = '%.1f' % (data['feet_apart']['percentile'] *10)
|
350 |
+
|
351 |
+
include_height_off_platform = False
|
352 |
+
height_off_board_score = data['height_off_board']['raw_score']
|
353 |
+
height_off_board_frame = None
|
354 |
+
height_off_board_percentile = None
|
355 |
+
height_off_board_percentile_divided_by_ten = None
|
356 |
+
height_off_board_description = None
|
357 |
+
encoded_height_off_board_frame = None
|
358 |
+
if height_off_board_score is not None:
|
359 |
+
include_height_off_platform = True
|
360 |
+
height_off_board_score = round(float('%.2f' % data['height_off_board']['raw_score']))
|
361 |
+
height_off_board_frame = Image.fromarray(cv2.cvtColor(frames[data['height_off_board']['frame_index']], cv2.COLOR_BGR2RGB))
|
362 |
+
height_buffer = BytesIO()
|
363 |
+
height_off_board_frame.save(height_buffer, format='JPEG')
|
364 |
+
encoded_height_off_board_frame = base64.b64encode(height_buffer.getvalue()).decode('utf-8')
|
365 |
+
height_off_board_percentile = round(float('%.2f' % (data['height_off_board']['percentile'] *100)))
|
366 |
+
height_off_board_percentile_divided_by_ten = '%.1f' % (data['height_off_board']['percentile'] *10)
|
367 |
+
if float(height_off_board_percentile_divided_by_ten) > 5:
|
368 |
+
height_off_board_description = "good"
|
369 |
+
else:
|
370 |
+
height_off_board_description = "a bit on the lower side"
|
371 |
+
|
372 |
+
dist_from_board_score = '%.2f' % data['distance_from_board']['raw_score']
|
373 |
+
dist_from_board_frame = Image.fromarray(cv2.cvtColor(frames[data['distance_from_board']['frame_index']], cv2.COLOR_BGR2RGB))
|
374 |
+
dist_buffer = BytesIO()
|
375 |
+
dist_from_board_frame.save(dist_buffer, format='JPEG')
|
376 |
+
encoded_dist_from_board_frame = base64.b64encode(dist_buffer.getvalue()).decode('utf-8')
|
377 |
+
dist_from_board_percentile = data['distance_from_board']['percentile']
|
378 |
+
if 'good' in dist_from_board_percentile:
|
379 |
+
dist_from_board_percentile_status = "Good"
|
380 |
+
elif 'far' in dist_from_board_percentile:
|
381 |
+
dist_from_board_percentile_status = "Too Far"
|
382 |
+
else:
|
383 |
+
dist_from_board_percentile_status = "Too Close"
|
384 |
+
|
385 |
+
knee_bend_score = data['knee_bend']['raw_score']
|
386 |
+
knee_bend_percentile = data['knee_bend']['percentile']
|
387 |
+
knee_bend_frames = []
|
388 |
+
knee_bend_percentile_divided_by_ten = None
|
389 |
+
if knee_bend_score is not None:
|
390 |
+
knee_bend_score = round(float('%.2f' % knee_bend_score))
|
391 |
+
knee_bend_percentile = round(float('%.2f' % (knee_bend_percentile * 100)))
|
392 |
+
knee_bend_frames = frames[data['knee_bend']['frame_indices']]
|
393 |
+
knee_bend_percentile_divided_by_ten = '%.1f' % (data['knee_bend']['percentile'] * 10)
|
394 |
+
|
395 |
+
som_position_tightness_score = data['som_position_tightness']['raw_score']
|
396 |
+
som_position_tightness_percentile = data['som_position_tightness']['percentile']
|
397 |
+
som_position_tightness_position = data['som_position_tightness']['position']
|
398 |
+
som_position_tightness_frames = []
|
399 |
+
som_position_tightness_gif = None
|
400 |
+
som_position_tightness_percentile_divided_by_ten = None
|
401 |
+
if som_position_tightness_score is not None:
|
402 |
+
if is_twister:
|
403 |
+
som_position_tightness_score = round(float('%.2f' % (data['som_position_tightness']['raw_score'] + 15)))
|
404 |
+
else:
|
405 |
+
som_position_tightness_score = round(float('%.2f' % (data['som_position_tightness']['raw_score'])))
|
406 |
+
som_position_tightness_frames = frames[data['som_position_tightness']['frame_indices']]
|
407 |
+
som_position_tightness_gif = generate_gif_from_frames(som_position_tightness_frames)
|
408 |
+
som_position_tightness_percentile = round(float('%.2f' % (som_position_tightness_percentile * 100)))
|
409 |
+
som_position_tightness_percentile_divided_by_ten = '%.1f' % (data['som_position_tightness']['percentile'] * 10)
|
410 |
+
|
411 |
+
twist_position_tightness_score = data['twist_position_tightness']['raw_score']
|
412 |
+
twist_position_tightness_frames = []
|
413 |
+
twist_position_tightness_gif = None
|
414 |
+
twist_position_tightness_percentile = None
|
415 |
+
twist_position_tightness_percentile_divided_by_ten = None
|
416 |
+
if twist_position_tightness_score is not None:
|
417 |
+
twist_position_tightness_score = round(float('%.2f' % twist_position_tightness_score))
|
418 |
+
twist_position_tightness_frames = frames[data['twist_position_tightness']['frame_indices']]
|
419 |
+
twist_position_tightness_gif = generate_gif_from_frames(twist_position_tightness_frames)
|
420 |
+
twist_position_tightness_percentile = round(float('%.2f' % (data['twist_position_tightness']['percentile'] * 100)))
|
421 |
+
twist_position_tightness_percentile_divided_by_ten = '%.1f' % (data['twist_position_tightness']['percentile'] * 10)
|
422 |
+
|
423 |
+
over_under_rotation_score = round(float('%.2f' % data['over_under_rotation']['raw_score']))
|
424 |
+
over_under_rotation_frame = frames[data['over_under_rotation']['frame_index']]
|
425 |
+
over_under_rotation_percentile = round(float('%.2f' % (data['over_under_rotation']['percentile'] * 100)))
|
426 |
+
over_under_rotation_percentile_divided_by_ten = '%.1f' % (data['over_under_rotation']['percentile'] * 10)
|
427 |
+
|
428 |
+
straightness_during_entry_score = round(float('%.2f' % data['straightness_during_entry']['raw_score']))
|
429 |
+
straightness_during_entry_frames = frames[data['straightness_during_entry']['frame_indices']]
|
430 |
+
straightness_during_entry_gif = generate_gif_from_frames(straightness_during_entry_frames, speed_factor = 0.5)
|
431 |
+
straightness_during_entry_percentile = round(float('%.2f' % (data['straightness_during_entry']['percentile'] * 100)))
|
432 |
+
straightness_during_entry_percentile_divided_by_ten = '%.1f' % (data['straightness_during_entry']['percentile'] * 10)
|
433 |
+
|
434 |
+
splash_score = round(float('%.2f' % data['splash']['raw_score']))
|
435 |
+
splash_frame = frames[data['splash']['maximum_index']]
|
436 |
+
splash_indices = frames[data['splash']['frame_indices']]
|
437 |
+
splash_gif = None
|
438 |
+
if len(splash_indices) > 0:
|
439 |
+
splash_gif = generate_gif_from_frames(splash_indices)
|
440 |
+
splash_percentile = round(float('%.2f' % (data['splash']['percentile'] * 100)))
|
441 |
+
splash_percentile_divided_by_ten = '%.1f' % (data['splash']['percentile'] * 10)
|
442 |
+
if float(splash_percentile) < 50:
|
443 |
+
splash_description = 'on the larger side'
|
444 |
+
else:
|
445 |
+
splash_description = 'small'
|
446 |
+
template = env.get_template(template_path)
|
447 |
+
data = {
|
448 |
+
'is_twister' : is_twister,
|
449 |
+
'overall_score_desc' : overall_score_desc,
|
450 |
+
'overall_score' : overall_score,
|
451 |
+
'feet_apart_score' : feet_apart_score,
|
452 |
+
'feet_apart_peaks' : feet_apart_peaks,
|
453 |
+
'has_feet_apart_peaks' : has_feet_apart_peaks,
|
454 |
+
'feet_apart_gif' : feet_apart_gif,
|
455 |
+
'feet_apart_percentile' : feet_apart_percentile,
|
456 |
+
'feet_apart_percentile_divided_by_ten': feet_apart_percentile_divided_by_ten,
|
457 |
+
'include_height_off_platform': include_height_off_platform,
|
458 |
+
'height_off_board_score' : height_off_board_score,
|
459 |
+
'height_off_board_percentile' : height_off_board_percentile,
|
460 |
+
'encoded_height_off_board_frame' : encoded_height_off_board_frame,
|
461 |
+
'height_off_board_percentile_divided_by_ten': height_off_board_percentile_divided_by_ten,
|
462 |
+
'height_off_board_description' : height_off_board_description,
|
463 |
+
'dist_from_board_score' : dist_from_board_score,
|
464 |
+
'dist_from_board_frame' : dist_from_board_frame,
|
465 |
+
'encoded_dist_from_board_frame': encoded_dist_from_board_frame,
|
466 |
+
'dist_from_board_percentile' : dist_from_board_percentile,
|
467 |
+
'dist_from_board_percentile_status': dist_from_board_percentile_status,
|
468 |
+
'knee_bend_score' : knee_bend_score,
|
469 |
+
'knee_bend_frames' : knee_bend_frames,
|
470 |
+
'knee_bend_percentile' : knee_bend_percentile,
|
471 |
+
'knee_bend_percentile_divided_by_ten' : knee_bend_percentile_divided_by_ten,
|
472 |
+
'som_position_tightness_score' : som_position_tightness_score,
|
473 |
+
'som_position_tightness_frames' : som_position_tightness_frames,
|
474 |
+
'som_position_tightness_gif' : som_position_tightness_gif,
|
475 |
+
'som_position_tightness_position' : som_position_tightness_position,
|
476 |
+
'som_position_tightness_percentile' : som_position_tightness_percentile,
|
477 |
+
'som_position_tightness_percentile_divided_by_ten' : som_position_tightness_percentile_divided_by_ten,
|
478 |
+
'twist_position_tightness_score' : twist_position_tightness_score,
|
479 |
+
'twist_position_tightness_frames': twist_position_tightness_frames,
|
480 |
+
'twist_position_tightness_percentile' : twist_position_tightness_percentile,
|
481 |
+
'twist_position_tightness_percentile_divided_by_ten' : twist_position_tightness_percentile_divided_by_ten,
|
482 |
+
'twist_position_tightness_gif' : twist_position_tightness_gif,
|
483 |
+
'over_under_rotation_score' : over_under_rotation_score,
|
484 |
+
'over_under_rotation_frame' : over_under_rotation_frame,
|
485 |
+
'over_under_rotation_percentile' : over_under_rotation_percentile,
|
486 |
+
'over_under_rotation_percentile_divided_by_ten' : over_under_rotation_percentile_divided_by_ten,
|
487 |
+
'straightness_during_entry_score' : straightness_during_entry_score,
|
488 |
+
'straightness_during_entry_gif' : straightness_during_entry_gif,
|
489 |
+
'straightness_during_entry_percentile' : straightness_during_entry_percentile,
|
490 |
+
'straightness_during_entry_percentile_divided_by_ten': straightness_during_entry_percentile_divided_by_ten,
|
491 |
+
'splash_score' : splash_score,
|
492 |
+
'splash_frame' : splash_frame,
|
493 |
+
'splash_gif' : splash_gif,
|
494 |
+
'splash_percentile' : splash_percentile,
|
495 |
+
'splash_percentile_divided_by_ten': splash_percentile_divided_by_ten,
|
496 |
+
'splash_description' : splash_description,
|
497 |
+
}
|
498 |
+
# Render the template with the provided data
|
499 |
+
report_content = template.render(data)
|
500 |
+
return report_content
|
501 |
+
|
502 |
+
def generate_symbols_report(template_path, dive_data, frames):
|
503 |
+
# Load the template environment
|
504 |
+
env = Environment(loader=FileSystemLoader('.'))
|
505 |
+
template = env.get_template(template_path)
|
506 |
+
pose_frames = []
|
507 |
+
for i in range(len(dive_data['pose_pred'])):
|
508 |
+
# if dive_data['pose_pred'][i] is not None:
|
509 |
+
pose_frame = draw_symbols(frames[i], dive_data['pose_pred'][i], dive_data['board_end_coords'][i], dive_data['plat_outputs'][i], dive_data['splash_pred_masks'][i])
|
510 |
+
pose_frames.append(pose_frame)
|
511 |
+
pose_gif = generate_gif_from_frames(pose_frames, speed_factor=2)
|
512 |
+
# image_buffer = BytesIO()
|
513 |
+
# pose_frame.save(image_buffer, format='JPEG')
|
514 |
+
# encoded_pose_frame = base64.b64encode(image_buffer.getvalue()).decode('utf-8')
|
515 |
+
pose_data = {}
|
516 |
+
pose_data['pose_gif'] = pose_gif
|
517 |
+
html = template.render(pose_data)
|
518 |
+
return html
|
519 |
+
|
520 |
+
def generate_symbols_report_precomputed(template_path, dive_data, local_directory, progress=gr.Progress()):
|
521 |
+
# Load the template environment
|
522 |
+
file_names = os.listdir(local_directory)
|
523 |
+
file_names.sort()
|
524 |
+
file_names = np.array(file_names)
|
525 |
+
|
526 |
+
if 'above_boards' in dive_data:
|
527 |
+
above_boards = dive_data['above_boards']
|
528 |
+
else:
|
529 |
+
above_boards = [None] * len(file_names)
|
530 |
+
|
531 |
+
env = Environment(loader=FileSystemLoader('.'))
|
532 |
+
template = env.get_template(template_path)
|
533 |
+
pose_frames = []
|
534 |
+
counter = 0
|
535 |
+
for i in range(len(file_names)):
|
536 |
+
progress(i/(len(file_names)+10), desc="Abstracting Symbols")
|
537 |
+
if file_names[i][-4:] != ".jpg":
|
538 |
+
continue
|
539 |
+
# if dive_data['pose_pred'][i] is not None:
|
540 |
+
opencv_image = cv2.imread(local_directory+file_names[i])
|
541 |
+
pose_frame = draw_symbols(opencv_image, dive_data['pose_pred'][counter], dive_data['board_end_coords'][counter], dive_data['plat_outputs'][counter], dive_data['splash_pred_masks'][counter], above_board=above_boards[counter])
|
542 |
+
pose_frames.append(pose_frame)
|
543 |
+
counter +=1
|
544 |
+
pose_gif = generate_gif_from_frames(pose_frames, speed_factor=2, progress=progress)
|
545 |
+
# image_buffer = BytesIO()
|
546 |
+
# pose_frame.save(image_buffer, format='JPEG')
|
547 |
+
# encoded_pose_frame = base64.b64encode(image_buffer.getvalue()).decode('utf-8')
|
548 |
+
pose_data = {}
|
549 |
+
pose_data['pose_gif'] = pose_gif
|
550 |
+
html = template.render(pose_data)
|
551 |
+
return html
|
platform.png
ADDED
pose_estimation.png
ADDED
report_template_tables.html
ADDED
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html>
|
3 |
+
<br>
|
4 |
+
<style>
|
5 |
+
table, th, td {
|
6 |
+
border:1px solid black;
|
7 |
+
}
|
8 |
+
</style>
|
9 |
+
<!-- <br> -->
|
10 |
+
<table style="width:100%">
|
11 |
+
<tr>
|
12 |
+
<td>Your dive was {{overall_score_desc}}, and scored a <strong>{{overall_score}}</strong>. Here is how we scored each component of the dive. Each percentile is relative to dives in the semifinals and finals of Olympic and World Championship competitions.</td>
|
13 |
+
</tr>
|
14 |
+
</table>
|
15 |
+
<table style="width:100%">
|
16 |
+
<tr>
|
17 |
+
<th style="width:10%">Error</th>
|
18 |
+
<th style="width:70%">Description</th>
|
19 |
+
<th style="width:60%">Visuals</th>
|
20 |
+
<th style="width:10%">Score</th>
|
21 |
+
</tr>
|
22 |
+
<tr>
|
23 |
+
<td>Feet Apart</td>
|
24 |
+
<td>We found that your leg separation angle was on average {{feet_apart_score}}° for your dive.
|
25 |
+
This is rated as {{feet_apart_percentile}} percentile.</td>
|
26 |
+
<td>
|
27 |
+
{% if has_feet_apart_peaks %}
|
28 |
+
<!-- gif -->
|
29 |
+
<img src="data:image/gif;base64,{{feet_apart_gif}}" alt="Feet Apart GIF" width="400" height="200">
|
30 |
+
{%else%}
|
31 |
+
There were no particular instances to show where your feet came apart.
|
32 |
+
{%endif%}
|
33 |
+
</td>
|
34 |
+
<td>
|
35 |
+
{{feet_apart_percentile_divided_by_ten}}
|
36 |
+
</td>
|
37 |
+
</tr>
|
38 |
+
{% if include_height_off_platform %}
|
39 |
+
<tr>
|
40 |
+
<td>Height off platform</td>
|
41 |
+
<td>Your jump was {{height_off_board_description}}, and was rated as {{height_off_board_percentile}} percentile. Here is the highest you jumped off the platform.</td>
|
42 |
+
<td>
|
43 |
+
<img src='data:image/jpg;base64, {{encoded_height_off_board_frame}}' width="400" height="200">
|
44 |
+
</td>
|
45 |
+
<td>
|
46 |
+
{{height_off_board_percentile_divided_by_ten}}
|
47 |
+
</td>
|
48 |
+
</tr>
|
49 |
+
{% endif %}
|
50 |
+
<tr>
|
51 |
+
<td>Distance from platform</td>
|
52 |
+
<td>You were {{dist_from_board_percentile}} the platform. Here is where you came closest to the platform.</td>
|
53 |
+
<td>
|
54 |
+
<!-- <img src='{{local_directory}}/{{dist_from_board_frame}}' width="200" height="100"> -->
|
55 |
+
<img src='data:image/jpg;base64, {{encoded_dist_from_board_frame}}' width="400" height="200">
|
56 |
+
</td>
|
57 |
+
<td>
|
58 |
+
{{dist_from_board_percentile_status}}
|
59 |
+
</td>
|
60 |
+
</tr>
|
61 |
+
{% if som_position_tightness_frames|length > 0 %}
|
62 |
+
<tr>
|
63 |
+
<td>Somersault tightness</td>
|
64 |
+
<td>
|
65 |
+
We found that the tightness of your {{som_position_tightness_position}} was {{som_position_tightness_score}}° on average.
|
66 |
+
This is rated as {{som_position_tightness_percentile}} percentile. Here are some examples of your position in the somersault.
|
67 |
+
</td>
|
68 |
+
{% if knee_bend_frames|length > 0 %}
|
69 |
+
<td rowspan="2">
|
70 |
+
<!-- gif -->
|
71 |
+
<img src="data:image/gif;base64,{{som_position_tightness_gif}}" alt="Somersault GIF" width="400" height="200">
|
72 |
+
</td>
|
73 |
+
{% else %}
|
74 |
+
<td>
|
75 |
+
<!-- gif -->
|
76 |
+
<img src="data:image/gif;base64,{{som_position_tightness_gif}}" alt="Somersault GIF" width="400" height="200">
|
77 |
+
</td>
|
78 |
+
{% endif %}
|
79 |
+
<td>
|
80 |
+
{{som_position_tightness_percentile_divided_by_ten}}
|
81 |
+
</td>
|
82 |
+
</tr>
|
83 |
+
{% endif %}
|
84 |
+
{% if knee_bend_frames|length > 0 %}
|
85 |
+
<tr>
|
86 |
+
<td>Knee straightness</td>
|
87 |
+
<td>
|
88 |
+
We found that your knees bent {{knee_bend_score}}° on average.
|
89 |
+
This is rated as {{knee_bend_percentile}} percentile.
|
90 |
+
</td>
|
91 |
+
<td>
|
92 |
+
{{knee_bend_percentile_divided_by_ten}}
|
93 |
+
</td>
|
94 |
+
</tr>
|
95 |
+
{% endif %}
|
96 |
+
{% if is_twister %}
|
97 |
+
<tr>
|
98 |
+
<td>
|
99 |
+
Twist Straightness
|
100 |
+
</td>
|
101 |
+
<td>
|
102 |
+
We found that the tightness of your {{twist_position_tightness_position}} was {{twist_position_tightness_score}}° on average.
|
103 |
+
This is rated as {{twist_position_tightness_percentile}} percentile. Here are some examples of your position in the somersault.
|
104 |
+
</td>
|
105 |
+
<td>
|
106 |
+
<!-- gif -->
|
107 |
+
<img src="data:image/gif;base64,{{twist_position_tightness_gif}}" alt="Twist GIF" width="400" height="200">
|
108 |
+
</td>
|
109 |
+
<td>
|
110 |
+
{{twist_position_tightness_percentile_divided_by_ten}}
|
111 |
+
</td>
|
112 |
+
</tr>
|
113 |
+
{% endif %}
|
114 |
+
<tr>
|
115 |
+
<td>
|
116 |
+
Verticalness (over/under rotation)
|
117 |
+
</td>
|
118 |
+
<td>
|
119 |
+
We found that you deviated from vertical by {{over_under_rotation_score}}°, which was the {{over_under_rotation_percentile}} percentile.
|
120 |
+
</td>
|
121 |
+
<td rowspan="2">
|
122 |
+
<!-- gif -->
|
123 |
+
<img src="data:image/gif;base64,{{straightness_during_entry_gif}}" alt="Entry GIF" width="400" height="200">
|
124 |
+
</td>
|
125 |
+
<td>
|
126 |
+
{{over_under_rotation_percentile_divided_by_ten}}
|
127 |
+
</td>
|
128 |
+
</tr>
|
129 |
+
<tr>
|
130 |
+
<td>Body straightness during entry</td>
|
131 |
+
<td>The straightness of your body during entry deviated by {{straightness_during_entry_score}}°, which was the {{straightness_during_entry_percentile}} percentile. </td>
|
132 |
+
<td>{{straightness_during_entry_percentile_divided_by_ten}}</td>
|
133 |
+
</tr>
|
134 |
+
<tr>
|
135 |
+
<td>Splash</td>
|
136 |
+
<td>Your splash was {{splash_description}} and rated as {{splash_percentile}} percentile. </td>
|
137 |
+
<td>
|
138 |
+
<!-- gif -->
|
139 |
+
<img src="data:image/gif;base64,{{splash_gif}}" alt="Splash GIF" width="400" height="200">
|
140 |
+
</td>
|
141 |
+
<td>
|
142 |
+
{{splash_percentile_divided_by_ten}}
|
143 |
+
</td>
|
144 |
+
</tr>
|
145 |
+
|
146 |
+
</table>
|
147 |
+
</html>
|
148 |
+
|
149 |
+
|
scoring_functions.py
ADDED
@@ -0,0 +1,579 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pickle
|
2 |
+
import numpy as np
|
3 |
+
import os
|
4 |
+
import math
|
5 |
+
from scipy.signal import find_peaks
|
6 |
+
from dive_recognition_functions import *
|
7 |
+
|
8 |
+
### All functions (excluding helper functions) take "dive_data" as input, which is the dictionary with all the information outputted by getAllErrorsAndSegmentation() in tempSegAndAllErrorsForAllFrames.py ###
|
9 |
+
|
10 |
+
############## HELPER FUNCTIONS ######################################
|
11 |
+
def rotation_direction(vector1, vector2, threshold=0.4):
|
12 |
+
# Calculate the determinant to determine rotation direction
|
13 |
+
determinant = vector1[0] * vector2[1] - vector1[1] * vector2[0]
|
14 |
+
mag1= np.linalg.norm(vector1)
|
15 |
+
mag2= np.linalg.norm(vector2)
|
16 |
+
norm_det = determinant/(mag1*mag2)
|
17 |
+
# print("determinant", determinant/(mag1*mag2))
|
18 |
+
# print(norm_det)
|
19 |
+
if norm_det > threshold:
|
20 |
+
# return "counterclockwise"
|
21 |
+
return 1
|
22 |
+
elif norm_det < 0-threshold:
|
23 |
+
# return "clockwise"
|
24 |
+
return -1
|
25 |
+
else:
|
26 |
+
# return "not determinent"
|
27 |
+
return 0
|
28 |
+
|
29 |
+
def find_angle(vector1, vector2):
|
30 |
+
unit_vector_1 = vector1 / np.linalg.norm(vector1)
|
31 |
+
unit_vector_2 = vector2 / np.linalg.norm(vector2)
|
32 |
+
dot_product = np.dot(unit_vector_1, unit_vector_2)
|
33 |
+
angle = math.degrees(np.arccos(dot_product))
|
34 |
+
return angle
|
35 |
+
|
36 |
+
#################################################################
|
37 |
+
|
38 |
+
def height_off_board_score(dive_data):
|
39 |
+
above_board_indices = [i for i in range(0, len(dive_data['distance_from_board'])) if dive_data['above_boards'][i]==1]
|
40 |
+
takeoff_indices = [i for i in range(0, len(dive_data['takeoff'])) if dive_data['takeoff'][i]==1]
|
41 |
+
final_indices = []
|
42 |
+
prev_board_end_coord = None
|
43 |
+
for i in range(len(above_board_indices)):
|
44 |
+
board_end_coord = dive_data['board_end_coords'][i]
|
45 |
+
if board_end_coord is not None and board_end_coord[1] < 30:
|
46 |
+
continue
|
47 |
+
if board_end_coord is not None and prev_board_end_coord is not None and math.dist(board_end_coord, prev_board_end_coord) > 150:
|
48 |
+
continue
|
49 |
+
if above_board_indices[i] not in takeoff_indices:
|
50 |
+
final_indices.append(above_board_indices[i])
|
51 |
+
prev_board_end_coord = board_end_coord
|
52 |
+
|
53 |
+
heights = []
|
54 |
+
for i in range(len(final_indices)):
|
55 |
+
pose_pred = dive_data['pose_pred'][final_indices[i]]
|
56 |
+
board_end_coord = dive_data['board_end_coords'][final_indices[i]]
|
57 |
+
if pose_pred is None or board_end_coord is None:
|
58 |
+
continue
|
59 |
+
pose_pred = pose_pred[0]
|
60 |
+
min_height = float('inf')
|
61 |
+
for j in range(len(pose_pred)):
|
62 |
+
if board_end_coord[1] - pose_pred[j][1]< min_height:
|
63 |
+
min_height = board_end_coord[1] - pose_pred[j][1]
|
64 |
+
if min_height < 0:
|
65 |
+
min_height = 0
|
66 |
+
heights.append(min_height)
|
67 |
+
if len(heights) == 0:
|
68 |
+
return None, None
|
69 |
+
max_scaled_height = max(heights) / get_scale_factor(dive_data)
|
70 |
+
return max_scaled_height, final_indices[np.argmax(heights)]
|
71 |
+
|
72 |
+
def distance_from_board_score(dive_data):
|
73 |
+
above_board_indices = [i for i in range(0, len(dive_data['distance_from_board'])) if dive_data['above_boards'][i]==1]
|
74 |
+
takeoff_indices = [i for i in range(0, len(dive_data['takeoff'])) if dive_data['takeoff'][i]==1]
|
75 |
+
final_indices = []
|
76 |
+
for i in range(len(above_board_indices)):
|
77 |
+
if above_board_indices[i] not in takeoff_indices:
|
78 |
+
final_indices.append(above_board_indices[i])
|
79 |
+
dists = np.array(dive_data['distance_from_board'])[final_indices]
|
80 |
+
for i in range(len(dists)):
|
81 |
+
if dists[i] is None:
|
82 |
+
dists[i] = float('inf')
|
83 |
+
# if np.min(dists) > 75:
|
84 |
+
# print(dive_data)
|
85 |
+
min_scaled_dist = np.min(dists) / get_scale_factor(dive_data)
|
86 |
+
too_close_threshold = 0.25
|
87 |
+
# if ground_truth[dive_data][0][:2] == '52':
|
88 |
+
# too_far_threshold = 1.1
|
89 |
+
# too_far_threshold is 75%tile
|
90 |
+
if 'diveNum' in dive_data:
|
91 |
+
if dive_data['diveNum'][0] == '4':
|
92 |
+
too_far_threshold = 1.1
|
93 |
+
if dive_data['diveNum'][0] == '1':
|
94 |
+
too_far_threshold = 1.6
|
95 |
+
if dive_data['diveNum'][0] == '2':
|
96 |
+
too_far_threshold = 1.8
|
97 |
+
if dive_data['diveNum'][0] == '3':
|
98 |
+
too_far_threshold = 1.6
|
99 |
+
if dive_data['diveNum'][0] == '5':
|
100 |
+
too_far_threshold = 1.5
|
101 |
+
if dive_data['diveNum'][0] == '6':
|
102 |
+
too_far_threshold = 1.1
|
103 |
+
else:
|
104 |
+
too_far_threshold = 1.8
|
105 |
+
# good distance
|
106 |
+
if min_scaled_dist < too_far_threshold and min_scaled_dist > too_close_threshold:
|
107 |
+
return 0, min_scaled_dist, final_indices[np.argmin(dists)]
|
108 |
+
# too far
|
109 |
+
if min_scaled_dist >= too_far_threshold:
|
110 |
+
return 1, min_scaled_dist, final_indices[np.argmin(dists)]
|
111 |
+
# too close
|
112 |
+
if min_scaled_dist <= too_close_threshold:
|
113 |
+
return -1, min_scaled_dist, final_indices[np.argmin(dists)]
|
114 |
+
return min_scaled_dist
|
115 |
+
|
116 |
+
def knee_bend_score(dive_data):
|
117 |
+
if find_position(dive_data) == 'tuck':
|
118 |
+
return None, None
|
119 |
+
knee_bends = []
|
120 |
+
for i in range(len(dive_data['pose_pred'])):
|
121 |
+
if dive_data['som'][i] == 0:
|
122 |
+
continue
|
123 |
+
pose_pred = dive_data['pose_pred'][i]
|
124 |
+
if pose_pred is None:
|
125 |
+
continue
|
126 |
+
pose_pred = pose_pred[0]
|
127 |
+
knee_to_ankle = [pose_pred[1][0] - pose_pred[0][0], 0-(pose_pred[1][1]-pose_pred[0][1])]
|
128 |
+
knee_to_hip = [pose_pred[1][0] - pose_pred[2][0], 0-(pose_pred[1][1]-pose_pred[2][1])]
|
129 |
+
knee_bend = find_angle(knee_to_ankle, knee_to_hip)
|
130 |
+
knee_bends.append(knee_bend)
|
131 |
+
if len(knee_bends) == 0:
|
132 |
+
return None, None
|
133 |
+
som_indices = [i for i in range(0, len(dive_data['som'])) if dive_data['som'][i]==1]
|
134 |
+
som_avg_knee_bend = np.mean(knee_bends)
|
135 |
+
return 180 - som_avg_knee_bend, som_indices
|
136 |
+
|
137 |
+
def position_tightness_score(dive_data):
|
138 |
+
som_indices = [i for i in range(0, len(dive_data['som'])) if dive_data['som'][i]==1]
|
139 |
+
twist_indices = [i for i in range(0, len(dive_data['som'])) if dive_data['twist'][i]==1]
|
140 |
+
som_tightness = np.array(dive_data['position_tightness'])[som_indices]
|
141 |
+
twist_tightness = 180 - np.array(dive_data['position_tightness'])[twist_indices]
|
142 |
+
|
143 |
+
# plt.plot(range(len(som_tightness)), som_tightness)
|
144 |
+
# plt.plot(range(len(twist_tightness)), twist_tightness)
|
145 |
+
# Compute the area using the composite trapezoidal rule.
|
146 |
+
som_tightness = np.array(list(filter(lambda item: item is not None and item < 90, som_tightness)))
|
147 |
+
twist_tightness = np.array(list(filter(lambda item: item is not None and item < 90, twist_tightness)))
|
148 |
+
if len(som_indices) == 0:
|
149 |
+
som_avg = None
|
150 |
+
else:
|
151 |
+
# som_area = np.trapz(som_tightness, dx=5) / len(som_tightness)
|
152 |
+
som_avg = np.mean(som_tightness)
|
153 |
+
# print("som area =", som_area)
|
154 |
+
if len(twist_indices)==0:
|
155 |
+
return som_avg, None, som_indices, twist_indices
|
156 |
+
# twist_area = np.trapz(twist_tightness, dx=5) / len(twist_tightness)
|
157 |
+
twist_avg = np.mean(twist_tightness)
|
158 |
+
if som_avg is not None:
|
159 |
+
som_avg -= 15
|
160 |
+
# print("twist area =",twist_area)
|
161 |
+
return som_avg, twist_avg, som_indices, twist_indices
|
162 |
+
|
163 |
+
def is_rotating_clockwise(dive_data):
|
164 |
+
directions = []
|
165 |
+
for i in range(1, len(dive_data['pose_pred'])):
|
166 |
+
if dive_data['pose_pred'][i] is None or dive_data['pose_pred'][i-1] is None:
|
167 |
+
continue
|
168 |
+
if dive_data['on_boards'][i] == 0:
|
169 |
+
prev_pose_pred_hip = dive_data['pose_pred'][i-1][0][3]
|
170 |
+
curr_pose_pred_hip = dive_data['pose_pred'][i][0][3]
|
171 |
+
prev_pose_pred_knee = dive_data['pose_pred'][i-1][0][4]
|
172 |
+
curr_pose_pred_knee = dive_data['pose_pred'][i][0][4]
|
173 |
+
prev_hip_knee = [prev_pose_pred_knee[0] - prev_pose_pred_hip[0], 0-(prev_pose_pred_knee[1] - prev_pose_pred_hip[1])]
|
174 |
+
curr_hip_knee = [curr_pose_pred_knee[0] - curr_pose_pred_hip[0], 0-(curr_pose_pred_knee[1] - curr_pose_pred_hip[1])]
|
175 |
+
direction = rotation_direction(prev_hip_knee, curr_hip_knee, threshold=0)
|
176 |
+
directions.append(direction)
|
177 |
+
return np.sum(directions) < 0
|
178 |
+
|
179 |
+
def over_under_rotation_score(dive_data):
|
180 |
+
entry_indices = [i for i in range(0, len(dive_data['entry'])) if dive_data['entry'][i]==1]
|
181 |
+
over_under_rotation_error = np.array(dive_data['over_under_rotation'])[entry_indices]
|
182 |
+
splashes = np.array(dive_data['splash'])[entry_indices]
|
183 |
+
for i in range(len(over_under_rotation_error) - 1, -1, -1):
|
184 |
+
if over_under_rotation_error[i] is None:
|
185 |
+
continue
|
186 |
+
else:
|
187 |
+
# gets the second to last pose (assuming the last pose has incorrect pose estimation)
|
188 |
+
# print(over_under_rotation_error[i-1]-90)
|
189 |
+
index = i-2
|
190 |
+
if index < 0:
|
191 |
+
index = 0
|
192 |
+
total_index = entry_indices[index]
|
193 |
+
if splashes[index] is None and over_under_rotation_error[index] is not None:
|
194 |
+
# print(entry_indices)
|
195 |
+
# print(entry_indices[i-3])
|
196 |
+
# return np.cos(math.radians(over_under_rotation_error[i-1]-90+10))
|
197 |
+
# avg_leg_torso = over_under_rotation_error[i-1]-90 +10 - straightness_during_entry_score(dive_data)
|
198 |
+
pose_pred = dive_data['pose_pred'][total_index][0]
|
199 |
+
thorax_pelvis_vector = [pose_pred[1][0] - pose_pred[7][0], 0-(pose_pred[1][1]-pose_pred[7][1])]
|
200 |
+
prev_pose_pred = dive_data['pose_pred'][total_index - 1]
|
201 |
+
if prev_pose_pred is not None:
|
202 |
+
# print(dive_data)
|
203 |
+
prev_pose_pred = prev_pose_pred[0]
|
204 |
+
prev_thorax_pelvis_vector = [prev_pose_pred[1][0] - prev_pose_pred[7][0], 0-(prev_pose_pred[1][1]-prev_pose_pred[7][1])]
|
205 |
+
rotation_speed = find_angle(thorax_pelvis_vector, prev_thorax_pelvis_vector)
|
206 |
+
else:
|
207 |
+
rotation_speed = 10
|
208 |
+
# print(rotation_speed)
|
209 |
+
vector2 = [0, 1]
|
210 |
+
# print(find_angle(thorax_pelvis_vector, vector2))
|
211 |
+
# print(thorax_pelvis_vector, prev_thorax_pelvis_vector)
|
212 |
+
if is_rotating_clockwise(dive_data):
|
213 |
+
# if under-rotated
|
214 |
+
if thorax_pelvis_vector[0] < 0:
|
215 |
+
avg_leg_torso = find_angle(thorax_pelvis_vector, vector2) - rotation_speed
|
216 |
+
|
217 |
+
else:
|
218 |
+
avg_leg_torso = find_angle(thorax_pelvis_vector, vector2) + rotation_speed
|
219 |
+
else:
|
220 |
+
# if over-rotated
|
221 |
+
if thorax_pelvis_vector[0] < 0:
|
222 |
+
avg_leg_torso = find_angle(thorax_pelvis_vector, vector2) + rotation_speed
|
223 |
+
else:
|
224 |
+
avg_leg_torso = find_angle(thorax_pelvis_vector, vector2) - rotation_speed
|
225 |
+
# avg_leg_torso = over_under_rotation_error[i-1]-90 +10 - np.array(dive_data['position_tightness'])[entry_indices][i-1]
|
226 |
+
return np.abs(avg_leg_torso), entry_indices[index]
|
227 |
+
break
|
228 |
+
|
229 |
+
def straightness_during_entry_score(dive_data):
|
230 |
+
entry_indices = [i for i in range(0, len(dive_data['entry'])) if dive_data['entry'][i]==1]
|
231 |
+
straightness_during_entry = np.array(dive_data['position_tightness'])[entry_indices]
|
232 |
+
over_under_rotation = over_under_rotation_score(dive_data)
|
233 |
+
if over_under_rotation is not None:
|
234 |
+
frame = over_under_rotation[1]
|
235 |
+
index = entry_indices.index(frame) - 1
|
236 |
+
if index < 0:
|
237 |
+
index = 0
|
238 |
+
return 180-straightness_during_entry[index], [frame-1, frame, frame + 1]
|
239 |
+
splashes = np.array(dive_data['splash'])[entry_indices]
|
240 |
+
for i in range(len(straightness_during_entry) - 1, -1, -1):
|
241 |
+
if i > 0 and (straightness_during_entry[i] is None or splashes[i] is not None):
|
242 |
+
continue
|
243 |
+
else:
|
244 |
+
# gets the second to last pose (assuming the last pose has incorrect pose estimation)
|
245 |
+
if straightness_during_entry[i] is not None:
|
246 |
+
if 180-straightness_during_entry[i] > 130:
|
247 |
+
continue
|
248 |
+
return 180-straightness_during_entry[i], entry_indices[i-1:i+2]
|
249 |
+
break
|
250 |
+
|
251 |
+
def splash_score(dive_data):
|
252 |
+
entry_indices = [i for i in range(0, len(dive_data['entry'])) if dive_data['entry'][i]==1]
|
253 |
+
if len(entry_indices) == 0:
|
254 |
+
return None
|
255 |
+
splash_indices=[i for i in range(0, len(dive_data['splash'])) if dive_data['splash'][i] is not None]
|
256 |
+
splashes = np.array(dive_data['splash'])[entry_indices]
|
257 |
+
for i in range(len(splashes)):
|
258 |
+
if splashes[i] is None:
|
259 |
+
splashes[i] = 0
|
260 |
+
splashes = splashes / get_scale_factor(dive_data)**2
|
261 |
+
|
262 |
+
# area under curve
|
263 |
+
# plt.plot(range(len(splashes)), splashes)
|
264 |
+
area = np.trapz(splashes, dx=5)
|
265 |
+
# print("area =", area)
|
266 |
+
|
267 |
+
# if area < 0.002:
|
268 |
+
# print(dive_data)
|
269 |
+
return area, entry_indices[np.argmax(splashes)], splash_indices
|
270 |
+
|
271 |
+
# feet apart
|
272 |
+
def feet_apart_score(dive_data):
|
273 |
+
takeoff_indices = [i for i in range(0, len(dive_data['takeoff'])) if dive_data['takeoff'][i]==1]
|
274 |
+
non_takeoff_indices = [i for i in range(len(dive_data['takeoff'])) if (i not in takeoff_indices and dive_data['splash'][i] is None)]
|
275 |
+
feet_apart_error = np.array(dive_data['feet_apart'])[non_takeoff_indices]
|
276 |
+
# plt.plot(range(len(feet_apart_error)), feet_apart_error)
|
277 |
+
for i in range(len(feet_apart_error)):
|
278 |
+
if feet_apart_error[i] is None or math.isnan(feet_apart_error[i]):
|
279 |
+
feet_apart_error[i] = 0
|
280 |
+
peaks, _ = find_peaks(feet_apart_error, height=5)
|
281 |
+
if len(peaks) >= 1:
|
282 |
+
peak_indices = np.array(non_takeoff_indices)[peaks]
|
283 |
+
# elif len(peaks) == 1:
|
284 |
+
# peak_indices = non_takeoff_indices[peaks[0]]
|
285 |
+
else:
|
286 |
+
peak_indices = []
|
287 |
+
# print(len(peaks))
|
288 |
+
# return peaks
|
289 |
+
# area = np.trapz(feet_apart_error, dx=5) /len(non_takeoff_indices)
|
290 |
+
area = np.mean(feet_apart_error)
|
291 |
+
|
292 |
+
# print(area)
|
293 |
+
return area, peak_indices
|
294 |
+
|
295 |
+
def find_position(dive_data):
|
296 |
+
angles = []
|
297 |
+
three_in_a_row = 0
|
298 |
+
for i in range(1, len(dive_data['pose_pred'])):
|
299 |
+
pose_pred = dive_data['pose_pred'][i]
|
300 |
+
if pose_pred is None or dive_data['som'][i]==0:
|
301 |
+
continue
|
302 |
+
pose_pred = pose_pred[0]
|
303 |
+
l_knee = pose_pred[4]
|
304 |
+
l_ankle = pose_pred[5]
|
305 |
+
l_hip = pose_pred[3]
|
306 |
+
l_knee_ankle = [l_ankle[0] - l_knee[0], 0-(l_ankle[1] - l_knee[1])]
|
307 |
+
l_knee_hip = [l_hip[0] - l_knee[0], 0-(l_hip[1] - l_knee[1])]
|
308 |
+
angle = find_angle(l_knee_ankle, l_knee_hip)
|
309 |
+
angles.append(angle)
|
310 |
+
# print(angle)
|
311 |
+
if angle < 70:
|
312 |
+
three_in_a_row += 1
|
313 |
+
if three_in_a_row >=3:
|
314 |
+
return 'tuck'
|
315 |
+
else:
|
316 |
+
three_in_a_row =0
|
317 |
+
# if np.mean(angles) < 100:
|
318 |
+
# return 'tuck'
|
319 |
+
# print(som_counter(dive_data))
|
320 |
+
# print(twist_counter(dive_data))
|
321 |
+
# if twist_counter_full_dive(dive_data) > 0 and som_counter_full_dive(dive_data)[0] < 5:
|
322 |
+
# return 'free'
|
323 |
+
return 'pike'
|
324 |
+
|
325 |
+
def get_position_from_diveNum(dive_data):
|
326 |
+
diveNum = dive_data['diveNum']
|
327 |
+
position_code = diveNum[-1]
|
328 |
+
if position_code == 'a':
|
329 |
+
return "straight"
|
330 |
+
elif position_code == 'b':
|
331 |
+
return "pike"
|
332 |
+
elif position_code == 'c':
|
333 |
+
return "tuck"
|
334 |
+
elif position_code == 'd':
|
335 |
+
return "free"
|
336 |
+
else:
|
337 |
+
return None
|
338 |
+
|
339 |
+
def get_all_report_scores(dive_data):
|
340 |
+
# with open('all_distributions.npy', 'rb') as f:
|
341 |
+
# feet_apart_scores = np.load(f)
|
342 |
+
# distance_from_board_scores = np.load(f)
|
343 |
+
# som_position_tightness_scores = np.load(f)
|
344 |
+
# twist_position_tightness_scores = np.load(f)
|
345 |
+
# over_under_rotation_scores = np.load(f)
|
346 |
+
# straightness_during_entry_scores = np.load(f)
|
347 |
+
# splash_scores = np.load(f)
|
348 |
+
with open('distribution_data.pkl', 'rb') as f:
|
349 |
+
distribution_data = pickle.load(f)
|
350 |
+
## handstand and som_count##
|
351 |
+
expected_som, handstand = som_counter_full_dive(dive_data)
|
352 |
+
## twist_count
|
353 |
+
expected_twists = twist_counter_full_dive(dive_data)
|
354 |
+
## direction: front, back, reverse, inward
|
355 |
+
expected_direction = get_direction(dive_data)
|
356 |
+
dive_data['is_handstand'] = handstand
|
357 |
+
dive_data['direction'] = expected_direction
|
358 |
+
|
359 |
+
intermediate_scores = {}
|
360 |
+
all_percentiles = []
|
361 |
+
entry_indices = [i for i in range(0, len(dive_data['entry'])) if dive_data['entry'][i]==1]
|
362 |
+
|
363 |
+
### height off board ###
|
364 |
+
if dive_data['is_handstand']:
|
365 |
+
error_scores = distribution_data['armstand_height_off_board_scores']
|
366 |
+
elif expected_twists >0:
|
367 |
+
error_scores = distribution_data['twist_height_off_board_scores']
|
368 |
+
elif dive_data['direction']=='front':
|
369 |
+
error_scores = distribution_data['front_height_off_board_scores']
|
370 |
+
elif dive_data['direction']=='back':
|
371 |
+
error_scores = distribution_data['back_height_off_board_scores']
|
372 |
+
elif dive_data['direction']=='reverse':
|
373 |
+
error_scores = distribution_data['reverse_height_off_board_scores']
|
374 |
+
elif dive_data['direction']=='inward':
|
375 |
+
error_scores = distribution_data['inward_height_off_board_scores']
|
376 |
+
error_scores = list(filter(lambda item: item is not None, error_scores))
|
377 |
+
intermediate_scores['height_off_board'] = {}
|
378 |
+
if dive_data['is_handstand']:
|
379 |
+
intermediate_scores['height_off_board']['raw_score'] = None
|
380 |
+
intermediate_scores['height_off_board']['frame_index'] = None
|
381 |
+
else:
|
382 |
+
intermediate_scores['height_off_board']['raw_score'] = height_off_board_score(dive_data)[0]
|
383 |
+
intermediate_scores['height_off_board']['frame_index'] = height_off_board_score(dive_data)[1]
|
384 |
+
err = intermediate_scores['height_off_board']['raw_score']
|
385 |
+
if err is not None:
|
386 |
+
temp = error_scores
|
387 |
+
temp.append(err)
|
388 |
+
temp.sort()
|
389 |
+
intermediate_scores['height_off_board']['percentile'] = temp.index(err)/len(temp)
|
390 |
+
all_percentiles.append(temp.index(err)/len(temp))
|
391 |
+
else:
|
392 |
+
intermediate_scores['height_off_board']['percentile'] = None
|
393 |
+
|
394 |
+
## distance from board ####
|
395 |
+
error_scores = distribution_data['distance_from_board_scores']
|
396 |
+
error_scores = list(filter(lambda item: item is not None, error_scores))
|
397 |
+
intermediate_scores['distance_from_board'] = {}
|
398 |
+
intermediate_scores['distance_from_board']['raw_score'] = distance_from_board_score(dive_data)[1]
|
399 |
+
intermediate_scores['distance_from_board']['frame_index'] = distance_from_board_score(dive_data)[2]
|
400 |
+
err = distance_from_board_score(dive_data)[0]
|
401 |
+
if err is not None:
|
402 |
+
if err == 1:
|
403 |
+
intermediate_scores['distance_from_board']['percentile'] = "safe, but too far from"
|
404 |
+
intermediate_scores['distance_from_board']['score'] = 0.5
|
405 |
+
|
406 |
+
elif err == 0:
|
407 |
+
intermediate_scores['distance_from_board']['percentile'] = "a good distance from"
|
408 |
+
intermediate_scores['distance_from_board']['score'] = 1
|
409 |
+
else:
|
410 |
+
intermediate_scores['distance_from_board']['percentile'] = "too close to"
|
411 |
+
intermediate_scores['distance_from_board']['score'] = 0
|
412 |
+
all_percentiles.append(intermediate_scores['distance_from_board']['score'])
|
413 |
+
else:
|
414 |
+
intermediate_scores['distance_from_board']['percentile'] = None
|
415 |
+
intermediate_scores['distance_from_board']['score'] = None
|
416 |
+
|
417 |
+
### feet_apart_scores ###
|
418 |
+
error_scores = distribution_data['feet_apart_scores']
|
419 |
+
error_scores = list(filter(lambda item: item is not None, error_scores))
|
420 |
+
intermediate_scores['feet_apart'] = {}
|
421 |
+
intermediate_scores['feet_apart']['raw_score'] = feet_apart_score(dive_data)[0]
|
422 |
+
intermediate_scores['feet_apart']['peaks'] = feet_apart_score(dive_data)[1]
|
423 |
+
err = intermediate_scores['feet_apart']['raw_score']
|
424 |
+
if err is not None:
|
425 |
+
temp = error_scores
|
426 |
+
temp.append(err)
|
427 |
+
temp.sort()
|
428 |
+
intermediate_scores['feet_apart']['percentile'] = 1-temp.index(err)/len(temp)
|
429 |
+
all_percentiles.append(1-temp.index(err)/len(temp))
|
430 |
+
else:
|
431 |
+
intermediate_scores['feet_apart']['percentile'] = None
|
432 |
+
|
433 |
+
### knee_bend_scores ###
|
434 |
+
error_scores = distribution_data['knee_bend_scores']
|
435 |
+
error_scores = list(filter(lambda item: item is not None, error_scores))
|
436 |
+
intermediate_scores['knee_bend'] = {}
|
437 |
+
intermediate_scores['knee_bend']['raw_score'] = knee_bend_score(dive_data)[0]
|
438 |
+
intermediate_scores['knee_bend']['frame_indices'] = knee_bend_score(dive_data)[1]
|
439 |
+
err = intermediate_scores['knee_bend']['raw_score']
|
440 |
+
if err is not None:
|
441 |
+
temp = error_scores
|
442 |
+
temp.append(err)
|
443 |
+
temp.sort()
|
444 |
+
intermediate_scores['knee_bend']['percentile'] = 1-temp.index(err)/len(temp)
|
445 |
+
all_percentiles.append(1-temp.index(err)/len(temp))
|
446 |
+
else:
|
447 |
+
intermediate_scores['knee_bend']['percentile'] = None
|
448 |
+
|
449 |
+
|
450 |
+
### som_position_tightness_scores ###
|
451 |
+
error_scores = distribution_data['som_position_tightness_scores']
|
452 |
+
error_scores = list(filter(lambda item: item is not None, error_scores))
|
453 |
+
intermediate_scores['som_position_tightness'] = {}
|
454 |
+
position = find_position(dive_data)
|
455 |
+
if position == 'tuck':
|
456 |
+
intermediate_scores['som_position_tightness']['position'] = 'tuck'
|
457 |
+
else:
|
458 |
+
intermediate_scores['som_position_tightness']['position'] = 'pike'
|
459 |
+
intermediate_scores['som_position_tightness']['raw_score'] = position_tightness_score(dive_data)[0]
|
460 |
+
intermediate_scores['som_position_tightness']['frame_indices'] = position_tightness_score(dive_data)[2]
|
461 |
+
err = intermediate_scores['som_position_tightness']['raw_score']
|
462 |
+
if err is not None:
|
463 |
+
temp = error_scores
|
464 |
+
temp.append(err)
|
465 |
+
temp.sort()
|
466 |
+
intermediate_scores['som_position_tightness']['percentile'] = 1-temp.index(err)/len(temp)
|
467 |
+
all_percentiles.append(1-temp.index(err)/len(temp))
|
468 |
+
else:
|
469 |
+
intermediate_scores['som_position_tightness']['percentile'] = None
|
470 |
+
|
471 |
+
### twist_position_tightness_scores ###
|
472 |
+
error_scores = distribution_data['twist_position_tightness_scores']
|
473 |
+
error_scores = list(filter(lambda item: item is not None, error_scores))
|
474 |
+
intermediate_scores['twist_position_tightness'] = {}
|
475 |
+
intermediate_scores['twist_position_tightness']['raw_score'] = position_tightness_score(dive_data)[1]
|
476 |
+
intermediate_scores['twist_position_tightness']['frame_indices'] = position_tightness_score(dive_data)[3]
|
477 |
+
err = intermediate_scores['twist_position_tightness']['raw_score']
|
478 |
+
if err is not None:
|
479 |
+
temp = error_scores
|
480 |
+
temp.append(err)
|
481 |
+
temp.sort()
|
482 |
+
intermediate_scores['twist_position_tightness']['percentile'] = 1-temp.index(err)/len(temp)
|
483 |
+
all_percentiles.append(1-temp.index(err)/len(temp))
|
484 |
+
else:
|
485 |
+
intermediate_scores['twist_position_tightness']['percentile'] = None
|
486 |
+
|
487 |
+
### over_under_rotation_scores ###
|
488 |
+
error_scores = distribution_data['over_under_rotation_scores']
|
489 |
+
error_scores = list(filter(lambda item: item is not None, error_scores))
|
490 |
+
intermediate_scores['over_under_rotation'] = {}
|
491 |
+
if over_under_rotation_score(dive_data) is not None:
|
492 |
+
intermediate_scores['over_under_rotation']['raw_score'] = over_under_rotation_score(dive_data)[0]
|
493 |
+
intermediate_scores['over_under_rotation']['frame_index'] = over_under_rotation_score(dive_data)[1]
|
494 |
+
else:
|
495 |
+
intermediate_scores['over_under_rotation']['raw_score'] = None
|
496 |
+
intermediate_scores['over_under_rotation']['frame_index'] = None
|
497 |
+
err = intermediate_scores['over_under_rotation']['raw_score']
|
498 |
+
if err is not None:
|
499 |
+
temp = error_scores
|
500 |
+
temp.append(err)
|
501 |
+
temp.sort()
|
502 |
+
intermediate_scores['over_under_rotation']['percentile'] = 1-temp.index(err)/len(temp)
|
503 |
+
all_percentiles.append(1-temp.index(err)/len(temp))
|
504 |
+
|
505 |
+
else:
|
506 |
+
intermediate_scores['over_under_rotation']['percentile'] = None
|
507 |
+
|
508 |
+
### splash_scores ###
|
509 |
+
error_scores = distribution_data['splash_scores']
|
510 |
+
error_scores = list(filter(lambda item: item is not None, error_scores))
|
511 |
+
intermediate_scores['splash'] = {}
|
512 |
+
intermediate_scores['splash']['raw_score'] = splash_score(dive_data)[0]
|
513 |
+
intermediate_scores['splash']['maximum_index'] = splash_score(dive_data)[1]
|
514 |
+
intermediate_scores['splash']['frame_indices'] = splash_score(dive_data)[2]
|
515 |
+
|
516 |
+
err = intermediate_scores['splash']['raw_score']
|
517 |
+
if err is not None:
|
518 |
+
temp = error_scores
|
519 |
+
temp.append(err)
|
520 |
+
temp.sort()
|
521 |
+
intermediate_scores['splash']['percentile'] = 1-temp.index(err)/len(temp)
|
522 |
+
all_percentiles.append(1-temp.index(err)/len(temp))
|
523 |
+
|
524 |
+
else:
|
525 |
+
intermediate_scores['splash']['percentile'] = None
|
526 |
+
|
527 |
+
### straightness_during_entry_scores ###
|
528 |
+
error_scores = distribution_data['straightness_during_entry_scores']
|
529 |
+
error_scores = list(filter(lambda item: item is not None, error_scores))
|
530 |
+
intermediate_scores['straightness_during_entry'] = {}
|
531 |
+
if straightness_during_entry_score(dive_data) is not None:
|
532 |
+
intermediate_scores['straightness_during_entry']['raw_score'] = straightness_during_entry_score(dive_data)[0]
|
533 |
+
intermediate_scores['straightness_during_entry']['frame_indices'] = straightness_during_entry_score(dive_data)[1]
|
534 |
+
else:
|
535 |
+
intermediate_scores['straightness_during_entry']['raw_score'] = None
|
536 |
+
intermediate_scores['straightness_during_entry']['frame_index'] = None
|
537 |
+
|
538 |
+
err = intermediate_scores['straightness_during_entry']['raw_score']
|
539 |
+
if err is not None:
|
540 |
+
temp = error_scores
|
541 |
+
temp.append(err)
|
542 |
+
temp.sort()
|
543 |
+
intermediate_scores['straightness_during_entry']['percentile'] = 1-temp.index(err)/len(temp)
|
544 |
+
all_percentiles.append(1-temp.index(err)/len(temp))
|
545 |
+
|
546 |
+
else:
|
547 |
+
intermediate_scores['straightness_during_entry']['percentile'] = None
|
548 |
+
|
549 |
+
## overall score ###
|
550 |
+
# Excellent: 10
|
551 |
+
# Very Good: 8.5-9.5
|
552 |
+
# Good: 7.0-8.0
|
553 |
+
# Satisfactory: 5.0-6.5
|
554 |
+
# Deficient: 2.5-4.5
|
555 |
+
# Unsatisfactory: 0.5-2.0
|
556 |
+
# Completely failed: 0
|
557 |
+
overall_score = np.mean(all_percentiles) * 10
|
558 |
+
intermediate_scores['overall_score'] = {}
|
559 |
+
intermediate_scores['overall_score']['raw_score'] = overall_score
|
560 |
+
if overall_score == 10:
|
561 |
+
intermediate_scores['overall_score']['description'] = 'excellent'
|
562 |
+
elif overall_score >=8.5 and overall_score <10:
|
563 |
+
intermediate_scores['overall_score']['description'] = 'very good'
|
564 |
+
elif overall_score >=7 and overall_score <8.5:
|
565 |
+
intermediate_scores['overall_score']['description'] = 'good'
|
566 |
+
elif overall_score >=5 and overall_score <7:
|
567 |
+
intermediate_scores['overall_score']['description'] = 'satisfactory'
|
568 |
+
elif overall_score >=2.5 and overall_score <5:
|
569 |
+
intermediate_scores['overall_score']['description'] = 'deficient'
|
570 |
+
elif overall_score >0 and overall_score <2.5:
|
571 |
+
intermediate_scores['overall_score']['description'] = 'unsatisfactory'
|
572 |
+
else:
|
573 |
+
intermediate_scores['overall_score']['description'] = 'completely failed'
|
574 |
+
|
575 |
+
return intermediate_scores
|
576 |
+
|
577 |
+
|
578 |
+
|
579 |
+
|
splash.png
ADDED
tempSegAndAllErrorsForAllFrames.py
ADDED
@@ -0,0 +1,201 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from microprograms.temporal_segmentation.entry import entry_microprogram_one_frame
|
2 |
+
from microprograms.temporal_segmentation.somersault import somersault_microprogram_one_frame
|
3 |
+
from microprograms.temporal_segmentation.twist import twist_microprogram_one_frame
|
4 |
+
from microprograms.temporal_segmentation.start_takeoff import takeoff_microprogram_one_frame
|
5 |
+
from microprograms.errors.distance_from_springboard_micro_program import board_end
|
6 |
+
from microprograms.errors.splash_micro_program import get_splash_from_one_frame
|
7 |
+
from microprograms.errors.distance_from_springboard_micro_program import calculate_distance_from_springboard_for_one_frame
|
8 |
+
from microprograms.errors.distance_from_springboard_micro_program import calculate_distance_from_platform_for_one_frame
|
9 |
+
from microprograms.errors.angles_micro_programs import applyFeetApartError
|
10 |
+
from microprograms.errors.angles_micro_programs import applyPositionTightnessError
|
11 |
+
from models.detectron2.platform_detector_setup import get_platform_detector
|
12 |
+
from models.pose_estimator.pose_estimator_model_setup import get_pose_estimation
|
13 |
+
from models.detectron2.diver_detector_setup import get_diver_detector
|
14 |
+
from models.pose_estimator.pose_estimator_model_setup import get_pose_model
|
15 |
+
from models.detectron2.splash_detector_setup import get_splash_detector
|
16 |
+
from somersault_counter import som_counter, twist_counter
|
17 |
+
from microprograms.errors.over_rotation import over_rotation
|
18 |
+
from temporal_segmentation import detect_on_board
|
19 |
+
import pickle
|
20 |
+
import os
|
21 |
+
import math
|
22 |
+
import numpy as np
|
23 |
+
import cv2
|
24 |
+
with open('segmentation_error_data.pkl', 'rb') as f:
|
25 |
+
data = pickle.load(f)
|
26 |
+
|
27 |
+
def getDiveInfo_from_diveNum(diveNum):
|
28 |
+
handstand = (diveNum[0] == '6')
|
29 |
+
expected_som = int(diveNum[2])
|
30 |
+
if len(diveNum) == 5:
|
31 |
+
expected_twists = int(diveNum[3])
|
32 |
+
else:
|
33 |
+
expected_twists = 0
|
34 |
+
if diveNum[0] == '1' or diveNum[0] == '3' or diveNum[:2] == '51' or diveNum[:2] == '53' or diveNum[:2] == '61' or diveNum[:2] == '63':
|
35 |
+
back_facing = False
|
36 |
+
else:
|
37 |
+
back_facing = True
|
38 |
+
if diveNum[0] == '1' or diveNum[:2] == '51' or diveNum[:2] == '61':
|
39 |
+
expected_direction = 'front'
|
40 |
+
elif diveNum[0] == '2' or diveNum[:2] == '52' or diveNum[:2] == '62':
|
41 |
+
expected_direction = 'back'
|
42 |
+
elif diveNum[0] == '3' or diveNum[:2] == '53' or diveNum[:2] == '63':
|
43 |
+
expected_direction = 'reverse'
|
44 |
+
elif diveNum[0] == '4':
|
45 |
+
expected_direction = 'inward'
|
46 |
+
if diveNum[-1] == 'b':
|
47 |
+
position = 'pike'
|
48 |
+
elif diveNum[-1] == 'c':
|
49 |
+
position = 'tuck'
|
50 |
+
else:
|
51 |
+
position = 'free'
|
52 |
+
return handstand, expected_som, expected_twists, back_facing, expected_direction, position
|
53 |
+
|
54 |
+
def getAllErrorsAndSegmentation(first_folder, second_folder, diveNum, board_side=None, platform_detector=None, splash_detector=None, diver_detector=None, pose_model=None):
|
55 |
+
handstand, expected_som, expected_twists, back_facing, expected_direction, position = getDiveInfo_from_diveNum(diveNum)
|
56 |
+
# first_folder = input("what is the first folder? Ex: 01, FINAWorldChampionships2019_Women10m_final_r1, etc. ")
|
57 |
+
# second_folder = input("what is the second folder? (dive within the first folder)")
|
58 |
+
dive_data = {}
|
59 |
+
takeoff = []
|
60 |
+
twist = []
|
61 |
+
som = []
|
62 |
+
entry = []
|
63 |
+
distance_from_board = []
|
64 |
+
position_tightness = []
|
65 |
+
feet_apart = []
|
66 |
+
over_under_rotation = []
|
67 |
+
splash = []
|
68 |
+
pose_preds = []
|
69 |
+
diver_boxes = []
|
70 |
+
above_boards = []
|
71 |
+
on_boards = []
|
72 |
+
som_counts = []
|
73 |
+
twist_counts = []
|
74 |
+
board_end_coords = []
|
75 |
+
plat_outputs = []
|
76 |
+
splash_pred_masks = []
|
77 |
+
above_board = True
|
78 |
+
on_board = True
|
79 |
+
if platform_detector is None:
|
80 |
+
platform_detector = get_platform_detector()
|
81 |
+
if splash_detector is None:
|
82 |
+
splash_detector = get_splash_detector()
|
83 |
+
if diver_detector is None:
|
84 |
+
diver_detector = get_diver_detector()
|
85 |
+
if pose_model is None:
|
86 |
+
pose_model = get_pose_model()
|
87 |
+
key = (first_folder, int(second_folder))
|
88 |
+
dive_folder_num = "{}_{}".format(first_folder, second_folder)
|
89 |
+
directory = './FineDiving/datasets/FINADiving_MTL_256s/{}/{}/'.format(first_folder, second_folder)
|
90 |
+
file_names = os.listdir(directory)
|
91 |
+
# with open('./output/joint_plots/{}/pose_preds.pkl'.format(dive_folder_num), 'rb') as pickle_file:
|
92 |
+
# pose_preds = pickle.load(pickle_file)
|
93 |
+
j = 0
|
94 |
+
prev_pred = None
|
95 |
+
som_prev_pred = None
|
96 |
+
half_som_count=0
|
97 |
+
petal_count = 0
|
98 |
+
in_petal = False
|
99 |
+
for i in range(len(file_names)):
|
100 |
+
# pose_pred = None
|
101 |
+
filepath = directory + file_names[i]
|
102 |
+
# print("filepath:", filepath)
|
103 |
+
if file_names[i][-4:] != ".jpg":
|
104 |
+
continue
|
105 |
+
diver_box, pose_pred = get_pose_estimation(filepath, diver_detector=diver_detector, pose_model=pose_model)
|
106 |
+
# pose_pred = data[key]['pose_pred'][i]
|
107 |
+
diver_boxes.append(diver_box)
|
108 |
+
pose_preds.append(pose_pred)
|
109 |
+
# if j < len(pose_preds):
|
110 |
+
# print("filepath has pose_pred:", filepath)
|
111 |
+
# pose_pred = pose_preds[j]
|
112 |
+
# j += 1
|
113 |
+
calculated_half_som_count, skip = som_counter(pose_pred, prev_pose_pred=som_prev_pred, half_som_count=half_som_count, handstand=handstand)
|
114 |
+
if not skip:
|
115 |
+
som_prev_pred = pose_pred
|
116 |
+
calculated_petal_count, calculated_in_petal = twist_counter(pose_pred, prev_pose_pred=prev_pred, in_petal=in_petal, petal_count=petal_count)
|
117 |
+
im = cv2.imread(filepath)
|
118 |
+
plat_output = platform_detector(im)
|
119 |
+
plat_outputs.append(plat_output)
|
120 |
+
board_end_coord = board_end(plat_output, board_side=board_side)
|
121 |
+
board_end_coords.append(board_end_coord)
|
122 |
+
# if board_end_coord is None:
|
123 |
+
# print("NO BOARD NONE CRYING")
|
124 |
+
if above_board and not on_board and board_end_coord is not None and pose_pred is not None and np.array(pose_pred)[0][2][1] > int(board_end_coord[1]):
|
125 |
+
above_board=False
|
126 |
+
if on_board and detect_on_board(board_end_coord, board_side, pose_pred, handstand) is not None and not detect_on_board(board_end_coord, board_side, pose_pred, handstand):
|
127 |
+
on_board = False
|
128 |
+
if above_board:
|
129 |
+
above_boards.append(1)
|
130 |
+
else:
|
131 |
+
above_boards.append(0)
|
132 |
+
if on_board:
|
133 |
+
on_boards.append(1)
|
134 |
+
else:
|
135 |
+
on_boards.append(0)
|
136 |
+
calculated_takeoff = takeoff_microprogram_one_frame(filepath, above_board=above_board, on_board=on_board, pose_pred=pose_pred)
|
137 |
+
calculated_twist = twist_microprogram_one_frame(filepath, on_board=on_board, pose_pred=pose_pred, expected_twists=expected_twists, petal_count=petal_count, expected_som=expected_som, half_som_count=half_som_count, diver_detector=diver_detector, pose_model=pose_model)
|
138 |
+
calculated_som = somersault_microprogram_one_frame(filepath, pose_pred=pose_pred, on_board=on_board, expected_som=expected_som, half_som_count=half_som_count, expected_twists=expected_twists, petal_count=petal_count, diver_detector=diver_detector, pose_model=pose_model)
|
139 |
+
calculated_entry = entry_microprogram_one_frame(filepath, above_board=above_board, on_board=on_board, pose_pred=pose_pred, expected_twists=expected_twists, petal_count=petal_count, expected_som=expected_som, half_som_count=half_som_count, splash_detector=splash_detector, visualize=False, dive_folder_num=dive_folder_num)
|
140 |
+
if calculated_som == 1:
|
141 |
+
half_som_count = calculated_half_som_count
|
142 |
+
elif calculated_twist == 1:
|
143 |
+
half_som_count = calculated_half_som_count
|
144 |
+
petal_count = calculated_petal_count
|
145 |
+
in_petal = calculated_in_petal
|
146 |
+
# distance from board
|
147 |
+
dist = calculate_distance_from_platform_for_one_frame(filepath, visualize=False, pose_pred=pose_pred, diver_detector=diver_detector, pose_model=pose_model, board_end_coord=board_end_coord, platform_detector=platform_detector) # saves photo to ./output/data/distance_from_board/
|
148 |
+
distance_from_board.append(dist)
|
149 |
+
position_tightness.append(applyPositionTightnessError(filepath, pose_pred=pose_pred, diver_detector=diver_detector, pose_model=pose_model))
|
150 |
+
feet_apart.append(applyFeetApartError(filepath, pose_pred=pose_pred, diver_detector=diver_detector, pose_model=pose_model))
|
151 |
+
over_under_rotation.append(over_rotation(filepath, pose_pred=pose_pred, diver_detector=diver_detector, pose_model=pose_model))
|
152 |
+
splash_area, splash_pred_mask = get_splash_from_one_frame(filepath, predictor=splash_detector, visualize=False)
|
153 |
+
splash.append(splash_area)
|
154 |
+
splash_pred_masks.append(splash_pred_mask)
|
155 |
+
takeoff.append(calculated_takeoff)
|
156 |
+
twist.append(calculated_twist)
|
157 |
+
som.append(calculated_som)
|
158 |
+
entry.append(calculated_entry)
|
159 |
+
som_counts.append(half_som_count)
|
160 |
+
twist_counts.append(petal_count)
|
161 |
+
prev_pred = pose_pred
|
162 |
+
|
163 |
+
dive_data['pose_pred'] = pose_preds
|
164 |
+
dive_data['takeoff'] = takeoff
|
165 |
+
dive_data['twist'] = twist
|
166 |
+
dive_data['som'] = som
|
167 |
+
dive_data['entry'] = entry
|
168 |
+
dive_data['distance_from_board'] = distance_from_board
|
169 |
+
dive_data['position_tightness'] = position_tightness
|
170 |
+
dive_data['feet_apart'] = feet_apart
|
171 |
+
dive_data['over_under_rotation'] = over_under_rotation
|
172 |
+
dive_data['splash'] = splash
|
173 |
+
dive_data['above_boards'] = above_boards
|
174 |
+
dive_data['on_boards'] = on_boards
|
175 |
+
dive_data['som_counts'] = som_counts
|
176 |
+
dive_data['twist_counts'] = twist_counts
|
177 |
+
dive_data['board_end_coords'] = board_end_coords
|
178 |
+
dive_data['diver_boxes'] = diver_boxes
|
179 |
+
dive_data['splash_pred_masks'] = splash_pred_masks
|
180 |
+
dive_data['plat_outputs'] = plat_outputs
|
181 |
+
dive_data['board_side'] = board_side
|
182 |
+
dive_data['is_handstand'] = handstand
|
183 |
+
dive_data['direction'] = expected_direction
|
184 |
+
|
185 |
+
print("takeoff", takeoff)
|
186 |
+
print("twist", twist)
|
187 |
+
print("som", som)
|
188 |
+
print("entry", entry)
|
189 |
+
print("distance_from_board", distance_from_board)
|
190 |
+
print("position_tightness", position_tightness)
|
191 |
+
print("feet_apart", feet_apart)
|
192 |
+
print("over_under_rotation", over_under_rotation)
|
193 |
+
print("splash", splash)
|
194 |
+
print("above_boards", above_boards)
|
195 |
+
print("on_boards", on_boards)
|
196 |
+
print("som_counts", som_counts)
|
197 |
+
print("twist_counts", twist_counts)
|
198 |
+
print("board_end_coords", board_end_coords)
|
199 |
+
print("diver_boxes", diver_boxes)
|
200 |
+
return dive_data
|
201 |
+
|
tempSegAndAllErrorsForAllFrames_newVids.py
ADDED
@@ -0,0 +1,312 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from microprograms.temporal_segmentation.entry import entry_microprogram_one_frame
|
2 |
+
from microprograms.temporal_segmentation.somersault import somersault_microprogram_one_frame
|
3 |
+
from microprograms.temporal_segmentation.twist import twist_microprogram_one_frame
|
4 |
+
from microprograms.temporal_segmentation.start_takeoff import takeoff_microprogram_one_frame
|
5 |
+
from microprograms.errors.distance_from_springboard_micro_program import board_end
|
6 |
+
from microprograms.errors.splash_micro_program import *
|
7 |
+
from microprograms.errors.distance_from_springboard_micro_program import calculate_distance_from_springboard_for_one_frame
|
8 |
+
from microprograms.errors.distance_from_springboard_micro_program import calculate_distance_from_platform_for_one_frame
|
9 |
+
from microprograms.errors.distance_from_springboard_micro_program import find_which_side_board_on
|
10 |
+
from microprograms.errors.angles_micro_programs import applyFeetApartError
|
11 |
+
from microprograms.errors.angles_micro_programs import applyPositionTightnessError
|
12 |
+
from models.detectron2.platform_detector_setup import get_platform_detector
|
13 |
+
from models.pose_estimator.pose_estimator_model_setup import get_pose_estimation
|
14 |
+
from models.detectron2.diver_detector_setup import get_diver_detector
|
15 |
+
from models.pose_estimator.pose_estimator_model_setup import get_pose_model
|
16 |
+
from models.detectron2.splash_detector_setup import get_splash_detector
|
17 |
+
from somersault_counter import som_counter, twist_counter
|
18 |
+
from microprograms.errors.over_rotation import over_rotation
|
19 |
+
from temporal_segmentation import detect_on_board
|
20 |
+
from dive_recognition_functions import *
|
21 |
+
from scoring_functions import get_scale_factor
|
22 |
+
import gradio as gr
|
23 |
+
import pickle
|
24 |
+
import os
|
25 |
+
import math
|
26 |
+
import numpy as np
|
27 |
+
import cv2
|
28 |
+
|
29 |
+
with open('segmentation_error_data.pkl', 'rb') as f:
|
30 |
+
data = pickle.load(f)
|
31 |
+
|
32 |
+
def getDiveInfo_from_diveNum(diveNum):
|
33 |
+
handstand = (diveNum[0] == '6')
|
34 |
+
expected_som = int(diveNum[2])
|
35 |
+
if len(diveNum) == 5:
|
36 |
+
expected_twists = int(diveNum[3])
|
37 |
+
else:
|
38 |
+
expected_twists = 0
|
39 |
+
if diveNum[0] == '1' or diveNum[0] == '3' or diveNum[:2] == '51' or diveNum[:2] == '53' or diveNum[:2] == '61' or diveNum[:2] == '63':
|
40 |
+
back_facing = False
|
41 |
+
else:
|
42 |
+
back_facing = True
|
43 |
+
if diveNum[0] == '1' or diveNum[:2] == '51' or diveNum[:2] == '61':
|
44 |
+
expected_direction = 'front'
|
45 |
+
elif diveNum[0] == '2' or diveNum[:2] == '52' or diveNum[:2] == '62':
|
46 |
+
expected_direction = 'back'
|
47 |
+
elif diveNum[0] == '3' or diveNum[:2] == '53' or diveNum[:2] == '63':
|
48 |
+
expected_direction = 'reverse'
|
49 |
+
elif diveNum[0] == '4':
|
50 |
+
expected_direction = 'inward'
|
51 |
+
if diveNum[-1] == 'b':
|
52 |
+
position = 'pike'
|
53 |
+
elif diveNum[-1] == 'c':
|
54 |
+
position = 'tuck'
|
55 |
+
else:
|
56 |
+
position = 'free'
|
57 |
+
return handstand, expected_som, expected_twists, back_facing, expected_direction, position
|
58 |
+
|
59 |
+
def getDiveInfo_from_symbols(frames, dive_data=None, platform_detector=None, splash_detector=None, diver_detector=None, pose_model=None):
|
60 |
+
print("Getting dive info from symbols...")
|
61 |
+
if dive_data is None:
|
62 |
+
print("somethings not getting passed in properly")
|
63 |
+
dive_data = abstractSymbols(frames, platform_detector=platform_detector, splash_detector=splash_detector, diver_detector=diver_detector, pose_model=pose_model)
|
64 |
+
|
65 |
+
# get above_boards, on_boards, and position_tightness
|
66 |
+
above_board = True
|
67 |
+
on_board = True
|
68 |
+
above_boards = []
|
69 |
+
on_boards = []
|
70 |
+
position_tightness = []
|
71 |
+
distances = []
|
72 |
+
prev_board_coord = None
|
73 |
+
for i in range(len(dive_data['pose_pred'])):
|
74 |
+
pose_pred = dive_data['pose_pred'][i]
|
75 |
+
board_end_coord = dive_data['board_end_coords'][i]
|
76 |
+
if board_end_coord is not None and prev_board_coord is not None:
|
77 |
+
distances.append(math.dist(board_end_coord, prev_board_coord))
|
78 |
+
if math.dist(board_end_coord, prev_board_coord) > 150:
|
79 |
+
position_tightness.append(applyPositionTightnessError(filepath="", pose_pred=pose_pred, diver_detector=diver_detector, pose_model=pose_model))
|
80 |
+
if above_board:
|
81 |
+
above_boards.append(1)
|
82 |
+
else:
|
83 |
+
above_boards.append(0)
|
84 |
+
if on_board:
|
85 |
+
on_boards.append(1)
|
86 |
+
else:
|
87 |
+
on_boards.append(0)
|
88 |
+
continue
|
89 |
+
if above_board and not on_board and board_end_coord is not None and pose_pred is not None and np.array(pose_pred)[0][2][1] > int(board_end_coord[1]):
|
90 |
+
above_board=False
|
91 |
+
if on_board:
|
92 |
+
handstand = is_handstand(dive_data)
|
93 |
+
calculate_on_board = detect_on_board(board_end_coord, dive_data['board_side'], pose_pred, handstand)
|
94 |
+
if calculate_on_board is not None and not calculate_on_board:
|
95 |
+
on_board = False
|
96 |
+
if above_board:
|
97 |
+
above_boards.append(1)
|
98 |
+
else:
|
99 |
+
above_boards.append(0)
|
100 |
+
if on_board:
|
101 |
+
on_boards.append(1)
|
102 |
+
else:
|
103 |
+
on_boards.append(0)
|
104 |
+
prev_board_coord = board_end_coord
|
105 |
+
position_tightness.append(applyPositionTightnessError(filepath="", pose_pred=pose_pred, diver_detector=diver_detector, pose_model=pose_model))
|
106 |
+
dive_data['on_boards'] = on_boards
|
107 |
+
dive_data['above_boards'] = above_boards
|
108 |
+
dive_data['position_tightness'] = position_tightness
|
109 |
+
|
110 |
+
## handstand and som_count##
|
111 |
+
expected_som, handstand = som_counter_full_dive(dive_data)
|
112 |
+
|
113 |
+
## twist_count
|
114 |
+
expected_twists = twist_counter_full_dive(dive_data)
|
115 |
+
|
116 |
+
## direction: front, back, reverse, inward
|
117 |
+
expected_direction = get_direction(dive_data)
|
118 |
+
|
119 |
+
return handstand, expected_som, expected_twists, expected_direction, dive_data
|
120 |
+
|
121 |
+
|
122 |
+
def abstractSymbols(frames, progress=gr.Progress(), platform_detector=None, splash_detector=None, diver_detector=None, pose_model=None):
|
123 |
+
print("Abstracting symbols...")
|
124 |
+
splashes = []
|
125 |
+
pose_preds = []
|
126 |
+
board_sides = []
|
127 |
+
plat_outputs = []
|
128 |
+
diver_boxes = []
|
129 |
+
splash_pred_masks = []
|
130 |
+
if platform_detector is None:
|
131 |
+
platform_detector = get_platform_detector()
|
132 |
+
if splash_detector is None:
|
133 |
+
splash_detector = get_splash_detector()
|
134 |
+
if diver_detector is None:
|
135 |
+
diver_detector = get_diver_detector()
|
136 |
+
if pose_model is None:
|
137 |
+
pose_model = get_pose_model()
|
138 |
+
num_frames = len(frames)
|
139 |
+
i = 0
|
140 |
+
for frame in frames:
|
141 |
+
progress(i/num_frames, desc="Abstracting Symbols")
|
142 |
+
plat_output = platform_detector(frame)
|
143 |
+
plat_outputs.append(plat_output)
|
144 |
+
board_side = find_which_side_board_on(plat_output)
|
145 |
+
if board_side is not None:
|
146 |
+
board_sides.append(board_side)
|
147 |
+
diver_box, pose_pred = get_pose_estimation(filepath="", image_bgr=frame, diver_detector=diver_detector, pose_model=pose_model)
|
148 |
+
pose_preds.append(pose_pred)
|
149 |
+
diver_boxes.append(diver_box)
|
150 |
+
splash_area, splash_pred_mask = get_splash_from_one_frame(filepath="", im=frame, predictor=splash_detector, visualize=False)
|
151 |
+
splash_pred_masks.append(splash_pred_mask)
|
152 |
+
splashes.append(splash_area)
|
153 |
+
i+=1
|
154 |
+
dive_data = {}
|
155 |
+
dive_data['plat_outputs'] = plat_outputs
|
156 |
+
dive_data['pose_pred'] = pose_preds
|
157 |
+
dive_data['splash'] = splashes
|
158 |
+
dive_data['splash_pred_masks'] = splash_pred_masks
|
159 |
+
dive_data['board_sides'] = board_sides
|
160 |
+
board_sides.sort()
|
161 |
+
board_side = board_sides[len(board_sides)//2]
|
162 |
+
dive_data['board_side'] = board_side
|
163 |
+
dive_data['diver_boxes'] = diver_boxes
|
164 |
+
|
165 |
+
# get board_end_coords
|
166 |
+
board_end_coords = []
|
167 |
+
for plat_output in dive_data['plat_outputs']:
|
168 |
+
board_end_coord = board_end(plat_output, board_side=dive_data['board_side'])
|
169 |
+
board_end_coords.append(board_end_coord)
|
170 |
+
dive_data['board_end_coords'] = board_end_coords
|
171 |
+
|
172 |
+
return dive_data
|
173 |
+
|
174 |
+
def getAllErrorsAndSegmentation_newVids(frames, dive_data, progress=gr.Progress(), diveNum="", board_side=None, platform_detector=None, splash_detector=None, diver_detector=None, pose_model=None):
|
175 |
+
print("in getAllErrorsAndSegmentation function...")
|
176 |
+
if len(frames) != len(dive_data['pose_pred']):
|
177 |
+
raise gr.Error("Abstract Symbols first!")
|
178 |
+
if diveNum != "":
|
179 |
+
dive_num_given = True
|
180 |
+
handstand, expected_som, expected_twists, back_facing, expected_direction, position = getDiveInfo_from_diveNum(diveNum)
|
181 |
+
else:
|
182 |
+
dive_num_given = False
|
183 |
+
handstand, expected_som, expected_twists, expected_direction, dive_data = getDiveInfo_from_symbols(frames, dive_data=dive_data, platform_detector=platform_detector, splash_detector=splash_detector, diver_detector=diver_detector, pose_model=pose_model)
|
184 |
+
|
185 |
+
if not dive_num_given:
|
186 |
+
above_boards = dive_data['above_boards']
|
187 |
+
on_boards = dive_data['on_boards']
|
188 |
+
position_tightness = dive_data['position_tightness']
|
189 |
+
board_end_coords = dive_data['board_end_coords']
|
190 |
+
else:
|
191 |
+
above_board = True
|
192 |
+
on_board = True
|
193 |
+
above_boards = []
|
194 |
+
on_boards = []
|
195 |
+
board_end_coords = []
|
196 |
+
position_tightness = []
|
197 |
+
splash = dive_data['splash']
|
198 |
+
diver_boxes = dive_data['diver_boxes']
|
199 |
+
board_side = dive_data['board_side']
|
200 |
+
pose_preds = dive_data['pose_pred']
|
201 |
+
takeoff = []
|
202 |
+
twist = []
|
203 |
+
som = []
|
204 |
+
entry = []
|
205 |
+
distance_from_board = []
|
206 |
+
feet_apart = []
|
207 |
+
over_under_rotation = []
|
208 |
+
som_counts = []
|
209 |
+
twist_counts = []
|
210 |
+
|
211 |
+
if platform_detector is None:
|
212 |
+
platform_detector = get_platform_detector()
|
213 |
+
if splash_detector is None:
|
214 |
+
splash_detector = get_splash_detector()
|
215 |
+
if diver_detector is None:
|
216 |
+
diver_detector = get_diver_detector()
|
217 |
+
if pose_model is None:
|
218 |
+
pose_model = get_pose_model()
|
219 |
+
j = 0
|
220 |
+
prev_pred = None
|
221 |
+
som_prev_pred = None
|
222 |
+
half_som_count=0
|
223 |
+
petal_count = 0
|
224 |
+
in_petal = False
|
225 |
+
num_frames = len(frames)
|
226 |
+
for i in range(num_frames):
|
227 |
+
progress(i/num_frames, desc="Calculating Dive Errors")
|
228 |
+
pose_pred = pose_preds[i]
|
229 |
+
calculated_half_som_count, skip = som_counter(pose_pred, prev_pose_pred=som_prev_pred, half_som_count=half_som_count, handstand=handstand)
|
230 |
+
if not skip:
|
231 |
+
som_prev_pred = pose_pred
|
232 |
+
calculated_petal_count, calculated_in_petal = twist_counter(pose_pred, prev_pose_pred=prev_pred, in_petal=in_petal, petal_count=petal_count)
|
233 |
+
if dive_num_given:
|
234 |
+
outputs = platform_detector(frames[i])
|
235 |
+
board_end_coord = board_end(outputs, board_side=board_side)
|
236 |
+
board_end_coords.append(board_end_coord)
|
237 |
+
if above_board and not on_board and board_end_coord is not None and pose_pred is not None and np.array(pose_pred)[0][2][1] > int(board_end_coord[1]):
|
238 |
+
above_board=False
|
239 |
+
if on_board and detect_on_board(board_end_coord, board_side, pose_pred, handstand) is not None and not detect_on_board(board_end_coord, board_side, pose_pred, handstand):
|
240 |
+
on_board = False
|
241 |
+
if above_board:
|
242 |
+
above_boards.append(1)
|
243 |
+
else:
|
244 |
+
above_boards.append(0)
|
245 |
+
if on_board:
|
246 |
+
on_boards.append(1)
|
247 |
+
else:
|
248 |
+
on_boards.append(0)
|
249 |
+
else:
|
250 |
+
board_end_coord = board_end_coords[i]
|
251 |
+
above_board = (above_boards[i] == 1)
|
252 |
+
on_board = (on_boards[i] == 1)
|
253 |
+
calculated_takeoff = takeoff_microprogram_one_frame(filepath="", above_board=above_board, on_board=on_board, pose_pred=pose_pred)
|
254 |
+
calculated_twist = twist_microprogram_one_frame(filepath="", on_board=on_board, pose_pred=pose_pred, expected_twists=expected_twists, petal_count=petal_count, expected_som=expected_som, half_som_count=half_som_count, diver_detector=diver_detector, pose_model=pose_model)
|
255 |
+
calculated_som = somersault_microprogram_one_frame(filepath="", pose_pred=pose_pred, on_board=on_board, expected_som=expected_som, half_som_count=half_som_count, expected_twists=expected_twists, petal_count=petal_count, diver_detector=diver_detector, pose_model=pose_model)
|
256 |
+
calculated_entry = entry_microprogram_one_frame(filepath="", frame=frames[i], above_board=above_board, on_board=on_board, pose_pred=pose_pred, expected_twists=expected_twists, petal_count=petal_count, expected_som=expected_som, half_som_count=half_som_count, splash_detector=splash_detector, visualize=False)
|
257 |
+
if calculated_som == 1:
|
258 |
+
half_som_count = calculated_half_som_count
|
259 |
+
elif calculated_twist == 1:
|
260 |
+
half_som_count = calculated_half_som_count
|
261 |
+
petal_count = calculated_petal_count
|
262 |
+
in_petal = calculated_in_petal
|
263 |
+
# distance from board
|
264 |
+
dist = calculate_distance_from_platform_for_one_frame(filepath="", im=frames[i], visualize=False, pose_pred=pose_pred, diver_detector=diver_detector, pose_model=pose_model, board_end_coord=board_end_coord, platform_detector=platform_detector) # saves photo to ./output/data/distance_from_board/
|
265 |
+
distance_from_board.append(dist)
|
266 |
+
if dive_num_given:
|
267 |
+
position_tightness.append(applyPositionTightnessError(filepath="", pose_pred=pose_pred, diver_detector=diver_detector, pose_model=pose_model))
|
268 |
+
# splash.append(get_splash_from_one_frame(filepath="", im=frames[i], predictor=splash_detector, visualize=False))
|
269 |
+
feet_apart.append(applyFeetApartError(filepath="", pose_pred=pose_pred, diver_detector=diver_detector, pose_model=pose_model))
|
270 |
+
over_under_rotation.append(over_rotation(filepath="", pose_pred=pose_pred, diver_detector=diver_detector, pose_model=pose_model))
|
271 |
+
takeoff.append(calculated_takeoff)
|
272 |
+
twist.append(calculated_twist)
|
273 |
+
som.append(calculated_som)
|
274 |
+
entry.append(calculated_entry)
|
275 |
+
som_counts.append(half_som_count)
|
276 |
+
twist_counts.append(petal_count)
|
277 |
+
prev_pred = pose_pred
|
278 |
+
print("takeoff", takeoff)
|
279 |
+
print("twist", twist)
|
280 |
+
print("som", som)
|
281 |
+
print("entry", entry)
|
282 |
+
print("distance_from_board", distance_from_board)
|
283 |
+
print("position_tightness", position_tightness)
|
284 |
+
print("feet_apart", feet_apart)
|
285 |
+
print("over_under_rotation", over_under_rotation)
|
286 |
+
print("splash", splash)
|
287 |
+
print("above_boards", above_boards)
|
288 |
+
print("on_boards", on_boards)
|
289 |
+
print("som_counts", som_counts)
|
290 |
+
print("twist_counts", twist_counts)
|
291 |
+
print("board_end_coords", board_end_coords)
|
292 |
+
print("diver_boxes", diver_boxes)
|
293 |
+
|
294 |
+
print("saving data into dive_data dictionary...")
|
295 |
+
dive_data['takeoff'] = takeoff
|
296 |
+
dive_data['twist'] = twist
|
297 |
+
dive_data['som'] = som
|
298 |
+
dive_data['entry'] = entry
|
299 |
+
dive_data['distance_from_board'] = distance_from_board
|
300 |
+
dive_data['position_tightness'] = position_tightness
|
301 |
+
dive_data['feet_apart'] = feet_apart
|
302 |
+
dive_data['over_under_rotation'] = over_under_rotation
|
303 |
+
dive_data['above_boards'] = above_boards
|
304 |
+
dive_data['on_boards'] = on_boards
|
305 |
+
dive_data['som_counts'] = som_counts
|
306 |
+
dive_data['twist_counts'] = twist_counts
|
307 |
+
dive_data['board_end_coords'] = board_end_coords
|
308 |
+
dive_data['is_handstand'] = handstand
|
309 |
+
dive_data['direction'] = expected_direction
|
310 |
+
return dive_data
|
311 |
+
|
312 |
+
|