| | import pickle |
| | import numpy as np |
| | import os |
| | import math |
| | from scipy.signal import find_peaks |
| | from matplotlib import pyplot as plt |
| |
|
| | def get_scale_factor(dive_data): |
| | |
| | distances = [] |
| | for pose_pred in dive_data['pose_pred']: |
| | if pose_pred is not None: |
| | distances.append(math.dist(pose_pred[0][6], pose_pred[0][7])) |
| | distances.sort() |
| | return np.median(distances) |
| |
|
| | def find_angle(vector1, vector2): |
| | unit_vector_1 = vector1 / np.linalg.norm(vector1) |
| | unit_vector_2 = vector2 / np.linalg.norm(vector2) |
| | dot_product = np.dot(unit_vector_1, unit_vector_2) |
| | angle = math.degrees(np.arccos(dot_product)) |
| | return angle |
| |
|
| | def is_back_facing(dive_data, board_side): |
| | directions = [] |
| | for i in range(len(dive_data['pose_pred'])): |
| | pose_pred = dive_data['pose_pred'][i] |
| | if pose_pred is None or dive_data['above_boards'][i] == 0: |
| | continue |
| | pose_pred = pose_pred[0] |
| | |
| | |
| | l_knee = pose_pred[4] |
| | l_ankle = pose_pred[5] |
| | l_hip = pose_pred[3] |
| | l_knee_ankle = [l_ankle[0] - l_knee[0], 0-(l_ankle[1] - l_knee[1])] |
| | l_knee_hip = [l_hip[0] - l_knee[0], 0-(l_hip[1] - l_knee[1])] |
| | l_direction = rotation_direction(l_knee_hip, l_knee_ankle) |
| | |
| | |
| | r_knee = pose_pred[1] |
| | r_ankle = pose_pred[0] |
| | r_hip = pose_pred[2] |
| | r_knee_ankle = [r_ankle[0] - r_knee[0], 0-(r_ankle[1] - r_knee[1])] |
| | r_knee_hip = [r_hip[0] - r_knee[0], 0-(r_hip[1] - r_knee[1])] |
| | r_direction = rotation_direction(r_knee_hip, r_knee_ankle) |
| | if l_direction == r_direction and l_direction != 0 and board_side == 'left': |
| | |
| | return l_direction < 0 |
| | elif l_direction == r_direction and l_direction != 0: |
| | |
| | return l_direction > 0 |
| | return False |
| |
|
| | def rotation_direction(vector1, vector2, threshold=0.4): |
| | |
| | determinant = vector1[0] * vector2[1] - vector1[1] * vector2[0] |
| | mag1= np.linalg.norm(vector1) |
| | mag2= np.linalg.norm(vector2) |
| | norm_det = determinant/(mag1*mag2) |
| | |
| | |
| | if norm_det > threshold: |
| | |
| | return 1 |
| | elif norm_det < 0-threshold: |
| | |
| | return -1 |
| | else: |
| | |
| | return 0 |
| |
|
| | def find_position(dive_data): |
| | angles = [] |
| | three_in_a_row = 0 |
| | for i in range(1, len(dive_data['pose_pred'])): |
| | pose_pred = dive_data['pose_pred'][i] |
| | if pose_pred is None or dive_data['som'][i]==0: |
| | continue |
| | pose_pred = pose_pred[0] |
| | l_knee = pose_pred[4] |
| | l_ankle = pose_pred[5] |
| | l_hip = pose_pred[3] |
| | l_knee_ankle = [l_ankle[0] - l_knee[0], 0-(l_ankle[1] - l_knee[1])] |
| | l_knee_hip = [l_hip[0] - l_knee[0], 0-(l_hip[1] - l_knee[1])] |
| | angle = find_angle(l_knee_ankle, l_knee_hip) |
| | angles.append(angle) |
| | |
| | if angle < 70: |
| | three_in_a_row += 1 |
| | if three_in_a_row >=3: |
| | return 'tuck' |
| | else: |
| | three_in_a_row =0 |
| | if twist_counter_full_dive(dive_data) > 0 and som_counter_full_dive(dive_data)[0] < 5: |
| | return 'free' |
| | return 'pike' |
| |
|
| |
|
| | def distance_point_to_line_segment(px, py, x1, y1, x2, y2): |
| | |
| | def sqr_distance_point_to_segment(): |
| | line_length_sq = (x2 - x1)**2 + (y2 - y1)**2 |
| | if line_length_sq == 0: |
| | return (px - x1)**2 + (py - y1)**2 |
| | t = max(0, min(1, ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / line_length_sq)) |
| | return ((px - (x1 + t * (x2 - x1)))**2 + (py - (y1 + t * (y2 - y1)))**2) |
| |
|
| | |
| | def closest_point_on_line_segment(): |
| | line_length_sq = (x2 - x1)**2 + (y2 - y1)**2 |
| | if line_length_sq == 0: |
| | return x1, y1 |
| | t = max(0, min(1, ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / line_length_sq)) |
| | closest_x = x1 + t * (x2 - x1) |
| | closest_y = y1 + t * (y2 - y1) |
| | return closest_x, closest_y |
| |
|
| | closest_point = closest_point_on_line_segment() |
| | distance = math.sqrt(sqr_distance_point_to_segment()) |
| |
|
| | return closest_point, distance |
| |
|
| | def min_distance_from_line_to_circle(line_start, line_end, circle_center, circle_radius): |
| | closest_point, distance = distance_point_to_line_segment(circle_center[0], circle_center[1], |
| | line_start[0], line_start[1], |
| | line_end[0], line_end[1]) |
| |
|
| | min_distance = max(0, distance - circle_radius) |
| | return min_distance |
| |
|
| |
|
| | def twister(pose_pred, prev_pose_pred=None, in_petal=False, petal_count=0, outer=10, inner=9, valid=17, middle=0.5): |
| | if pose_pred is None: |
| | return petal_count, in_petal |
| | min_dist = 0 |
| | |
| | pose_pred = pose_pred[0] |
| | vector1 = [pose_pred[2][0] - pose_pred[3][0], 0-(pose_pred[2][1] - pose_pred[3][1])] |
| | if prev_pose_pred is not None: |
| | prev_pose_pred = prev_pose_pred[0] |
| | prev_pose_pred = [prev_pose_pred[2][0] - prev_pose_pred[3][0], 0-(prev_pose_pred[2][1] - prev_pose_pred[3][1])] |
| | min_dist = min_distance_from_line_to_circle(prev_pose_pred, vector1, (0, 0), middle) |
| | if np.linalg.norm(vector1) > valid: |
| | return petal_count, in_petal |
| | if min_dist is not None and in_petal and np.linalg.norm(vector1) > outer and min_dist == 0: |
| | petal_count += 1 |
| | |
| | |
| | elif not in_petal and np.linalg.norm(vector1) > outer: |
| | in_petal = True |
| | petal_count += 1 |
| | |
| | elif in_petal and np.linalg.norm(vector1) < inner: |
| | in_petal = False |
| | |
| | |
| | |
| | return petal_count, in_petal |
| |
|
| |
|
| | def twist_counter_full_dive(dive_data, visualize=False): |
| | twists_gt = [] |
| | twists_gt.extend(range(29, 36)) |
| | twists_gt.extend([41, 42]) |
| | start = [1, 2, 3, 4, 5, 6, 7] |
| | |
| | |
| | |
| | dist_hip = [] |
| | prev_pose_pred = None |
| | in_petal=False |
| | petal_count=0 |
| | scale = get_scale_factor(dive_data) |
| | valid = scale / 1.5 |
| | outer = scale / 3.2 |
| | inner = scale / 3.4 |
| | middle = 0.5 |
| | next_next_pose_pred = dive_data['pose_pred'][4] |
| | |
| | for i in range(len(dive_data['pose_pred'])): |
| | |
| | |
| | |
| | |
| | pose_pred = dive_data['pose_pred'][i] |
| | if i < len(dive_data['pose_pred']) - 1: |
| | next_pose_pred = dive_data['pose_pred'][i + 1] |
| | if i < len(dive_data['pose_pred']) - 4 and next_next_pose_pred is not None: |
| | next_next_pose_pred = dive_data['pose_pred'][i + 4] |
| | 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: |
| | continue |
| | 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) |
| | prev_pose_pred = pose_pred |
| | |
| | if visualize: |
| | pose_pred = pose_pred[0] |
| | dist_hip.append([pose_pred[2][0] - pose_pred[3][0], 0-(pose_pred[2][1] - pose_pred[3][1])]) |
| | if visualize: |
| | dist_hip = np.array(dist_hip) |
| | plt.plot(dist_hip[:, 0], dist_hip[:, 1], label="right-to-left hip") |
| | circle1 = plt.Circle((0, 0), outer, fill=False) |
| | plt.gca().add_patch(circle1) |
| | circle2 = plt.Circle((0, 0), inner, fill=False) |
| | plt.gca().add_patch(circle2) |
| | circle3 = plt.Circle((0, 0), valid, fill=False) |
| | plt.gca().add_patch(circle3) |
| | plt.legend() |
| | plt.show() |
| | return petal_count |
| |
|
| | def rotation_direction_som(vector1, vector2, threshold=0.4): |
| | |
| | determinant = vector1[0] * vector2[1] - vector1[1] * vector2[0] |
| | mag1= np.linalg.norm(vector1) |
| | mag2= np.linalg.norm(vector2) |
| | norm_det = determinant/(mag1*mag2) |
| | theta = np.arcsin(norm_det) |
| | return math.degrees(theta) |
| |
|
| | def is_handstand(dive_data): |
| | first_frame_pose_pred = dive_data['pose_pred'][0] |
| | handstand = False |
| | if first_frame_pose_pred[0][6][1] < first_frame_pose_pred[0][7][1]: |
| | handstand = True |
| | return handstand |
| | |
| | def som_counter_full_dive(dive_data, visualize=False): |
| | start = [1, 2, 3, 4, 5, 6, 7] |
| | entry = [36] |
| | half_som_count = 0 |
| | |
| | |
| | dist_body = [] |
| | handstand = is_handstand(dive_data) |
| | |
| | next_next_pose_pred = dive_data['pose_pred'][2] |
| | |
| | prev = None |
| | for i in range(len(dive_data['pose_pred'])): |
| | |
| | |
| | pose_pred = dive_data['pose_pred'][i] |
| | if i < len(dive_data['pose_pred']) - 2 and next_next_pose_pred is not None: |
| | next_next_pose_pred = dive_data['pose_pred'][i + 2] |
| | if pose_pred is None or next_next_pose_pred is None or dive_data['on_boards'][i] == 1: |
| | continue |
| | |
| | pose_pred = pose_pred[0] |
| | vector1 = [pose_pred[7][0] - pose_pred[6][0], 0-(pose_pred[7][1] - pose_pred[6][1])] |
| | if (not handstand and half_som_count % 2 == 0) or (handstand and half_som_count % 2 == 1): |
| | vector2 = [0, -1] |
| | else: |
| | vector2 = [0, 1] |
| | sensitivity = 115 |
| | if prev is not None and find_angle(vector1, prev) > sensitivity: |
| | continue |
| | is_clockwise = is_rotating_clockwise(dive_data) |
| | 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)): |
| | continue |
| | angle = find_angle(vector1, vector2) |
| | |
| | |
| | |
| | |
| | if angle <= 75: |
| | half_som_count += 1 |
| | if visualize: |
| | dist_body.append([pose_pred[7][0] - pose_pred[6][0], 0-(pose_pred[7][1] - pose_pred[6][1])]) |
| | prev = vector1 |
| | |
| | if visualize: |
| | dist_body = np.array(dist_body) |
| | plt.plot(dist_body[:, 0], dist_body[:, 1], label="pelvis-to-thorax") |
| | plt.xlabel("x-coord") |
| | plt.ylabel("y-coord") |
| |
|
| | plt.legend() |
| | plt.show() |
| | return half_som_count, handstand |
| |
|
| | def getDiveInfo(diveNum): |
| | handstand = (diveNum[0] == '6') |
| | expected_som = int(diveNum[2]) |
| | if len(diveNum) == 5: |
| | expected_twists = int(diveNum[3]) |
| | else: |
| | expected_twists = 0 |
| | if diveNum[0] == '1' or diveNum[0] == '3' or diveNum[:2] == '51' or diveNum[:2] == '53' or diveNum[:2] == '61' or diveNum[:2] == '63': |
| | back_facing = False |
| | else: |
| | back_facing = True |
| | if diveNum[0] == '1' or diveNum[:2] == '51' or diveNum[:2] == '61': |
| | expected_direction = 'front' |
| | elif diveNum[0] == '2' or diveNum[:2] == '52' or diveNum[:2] == '62': |
| | expected_direction = 'back' |
| | elif diveNum[0] == '3' or diveNum[:2] == '53' or diveNum[:2] == '63': |
| | expected_direction = 'reverse' |
| | elif diveNum[0] == '4': |
| | expected_direction = 'inward' |
| | if diveNum[-1] == 'b': |
| | position = 'pike' |
| | elif diveNum[-1] == 'c': |
| | position = 'tuck' |
| | else: |
| | position = 'free' |
| | return handstand, expected_som, expected_twists, back_facing, expected_direction, position |
| |
|
| | def get_direction(dive_data): |
| | clockwise = is_rotating_clockwise(dive_data) |
| | board_side = dive_data['board_side'] |
| | if board_side == "right": |
| | back_facing = is_back_facing(dive_data, 'right') |
| | if back_facing and clockwise: |
| | direction = 'inward' |
| | elif back_facing and not clockwise: |
| | direction = 'back' |
| | elif not back_facing and clockwise: |
| | direction = 'reverse' |
| | elif not back_facing and not clockwise: |
| | direction = 'front' |
| | else: |
| | back_facing = is_back_facing(dive_data, 'left') |
| | if back_facing and clockwise: |
| | direction = 'back' |
| | elif back_facing and not clockwise: |
| | direction = 'inward' |
| | elif not back_facing and clockwise: |
| | direction = 'front' |
| | elif not back_facing and not clockwise: |
| | direction = 'reverse' |
| | return direction |
| |
|
| | def is_rotating_clockwise(dive_data): |
| | directions = [] |
| | for i in range(1, len(dive_data['pose_pred'])): |
| | if dive_data['pose_pred'][i] is None or dive_data['pose_pred'][i-1] is None: |
| | continue |
| | if dive_data['on_boards'][i] == 0: |
| | prev_pose_pred_hip = dive_data['pose_pred'][i-1][0][3] |
| | curr_pose_pred_hip = dive_data['pose_pred'][i][0][3] |
| | prev_pose_pred_knee = dive_data['pose_pred'][i-1][0][4] |
| | curr_pose_pred_knee = dive_data['pose_pred'][i][0][4] |
| | prev_hip_knee = [prev_pose_pred_knee[0] - prev_pose_pred_hip[0], 0-(prev_pose_pred_knee[1] - prev_pose_pred_hip[1])] |
| | curr_hip_knee = [curr_pose_pred_knee[0] - curr_pose_pred_hip[0], 0-(curr_pose_pred_knee[1] - curr_pose_pred_hip[1])] |
| | direction = rotation_direction(prev_hip_knee, curr_hip_knee, threshold=0) |
| | directions.append(direction) |
| | return np.sum(directions) < 0 |
| |
|
| |
|
| |
|
| |
|