File size: 7,336 Bytes
b9cc655
a3281f6
b9cc655
 
 
 
 
 
 
 
 
 
 
a3281f6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c9ec478
 
 
b9cc655
 
a3281f6
 
 
 
 
b9cc655
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a3281f6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b9cc655
 
a3281f6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2c8cacd
 
c9ec478
a3281f6
c9ec478
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import numpy as np
import pandas as pd

def get_width(mask, keypoint_y):
    pred_np = mask.numpy()
    # Find the index of the first occurrence of the mask label
    first_index = np.argmax(pred_np[keypoint_y,:] > 0)

    # Find the index of the last occurrence of the mask label
    last_index = len(pred_np[keypoint_y,:]) - np.argmax(np.flip(pred_np[keypoint_y,:]) > 0) - 1

    return last_index-first_index

def calculate_bbox(original_image, keypoint_1, keypoint_2):
    # Determine bounding box coordinates
    min_x = 0
    min_y = int(min(keypoint_1[1], keypoint_2[1]))
    max_y = int(max(keypoint_1[1], keypoint_2[1]))
    # Set max_x to be the width of the image
    max_x = original_image.size[0]
    return [min_x, max_x, min_y, max_y]

def get_volume_result(mask_of_interest, original_image, max_x, min_x, max_y, min_y):
    # thr = mask_of_interest[mask_of_interest > 0].mean()
    thr = 0
    if min_x < 0 or max_x > mask_of_interest.shape[1] or min_y < 0 or max_y > mask_of_interest.shape[0]:
        print("Warning: Invalid indices for slicing.")
    if min_x < max_x and min_y < max_y:
        region_inside_bounding_box = mask_of_interest[min_y:max_y, min_x:max_x] > thr
        return region_inside_bounding_box.sum()
    else:
        print("Invalid bounding box indices.")
    return None

def calculate_all_measures(front_image, side_image, front_keypoint_data, side_keypoint_data, front_seg_mask, side_rcnn_mask):
    # Initialize an empty DataFrame
    results = []

    results_dict = {}

    front_keypoints = front_keypoint_data['keypoints']
    front_keypoint_names = front_keypoint_data['keypoint_names']
    side_keypoints = side_keypoint_data['keypoints']
    side_keypoint_names = side_keypoint_data['keypoint_names']

    # calculate the body length
    # pick the longer from the two ankle keypoints on y coordinate
    side_body_length = side_keypoints[15][1] if side_keypoints[15][1] > side_keypoints[16][1] else side_keypoints[16][1]

    #     5: 'left_shoulder'
    left_shoulder_y = round(front_keypoints[5][1])
    # print("shoulder width", get_width(front_seg_mask, left_shoulder_y))
    results_dict['shoulder_width'] = get_width(front_seg_mask, left_shoulder_y)

    # remove left-arm mask
    front_seg_mask[front_seg_mask == 14] = 0

    # remove right-arm mask
    front_seg_mask[front_seg_mask == 15] = 0

    #     11: 'left_hip'
    left_hip_y = round(front_keypoints[11][1])
    # print("hip width", get_width(front_seg_mask, left_hip_y))
    results_dict['hip_width'] = get_width(front_seg_mask, left_hip_y)

    # calculate shoulder_to_hip distance
    shoulder_to_hip_distance = front_keypoints[11][1] - front_keypoints[5][1]
    # print("Shoulder to hip distance:", shoulder_to_hip_distance)
    results_dict['shoulder_to_hip_distance'] = shoulder_to_hip_distance

    # calculate hip_to_ankle distance
    hip_to_ankle_distance = front_keypoints[16][1] - front_keypoints[12][1]
    # print("Hip to ankle distance:", hip_to_ankle_distance)
    results_dict['hip_to_ankle_distance'] = hip_to_ankle_distance

    # calculate torso_to_leg proportions
    torso_to_leg_proportions = shoulder_to_hip_distance / hip_to_ankle_distance
    # print("Torso to leg proportions:", torso_to_leg_proportions)
    results_dict['torso_to_leg_ratio'] = torso_to_leg_proportions

    # waist 
    # assuming waistline is x % higher from hips 
    # hip_y axis - (40 % of shoulder to hip distance)
    waist_y = round(front_keypoints[11][1] - (shoulder_to_hip_distance * 0.40))
    # print("waist width", get_width(front_seg_mask, waist_y))
    results_dict['waist_width'] = get_width(front_seg_mask, waist_y)

    # Calculate bounding box for thigh
    right_knee = side_keypoints[side_keypoint_names.index("right_knee")]
    right_hip = side_keypoints[side_keypoint_names.index("right_hip")]
    # Calculate bounding box for torso
    right_shoulder = side_keypoints[side_keypoint_names.index("right_shoulder")]

    # Replace keypoints, keypoint_names, combined_mask, and original_image with your actual data
    thigh_bbox = calculate_bbox(side_image, right_knee, right_hip)
    torso_bbox = calculate_bbox(side_image, right_hip, right_shoulder)
    # Calculate midpoint coordinates
    torso_midpoint = [0, (right_hip[1] + right_shoulder[1]) / 2]
    lower_torso_bbox = calculate_bbox(side_image, right_hip, torso_midpoint)
    upper_torso_bbox = calculate_bbox(side_image, torso_midpoint, right_shoulder)

    # Replace keypoints, keypoint_names, combined_mask, and original_image with your actual data
    thigh_area = get_volume_result(side_rcnn_mask, side_image, thigh_bbox[1], thigh_bbox[0], thigh_bbox[3], thigh_bbox[2]) # Thigh volume
    torso_area = get_volume_result(side_rcnn_mask, side_image, torso_bbox[1], torso_bbox[0], torso_bbox[3], torso_bbox[2]) # Torso volume
    lower_torso_area = get_volume_result(side_rcnn_mask, side_image, lower_torso_bbox[1], lower_torso_bbox[0], lower_torso_bbox[3], lower_torso_bbox[2]) # Lower torso volume
    upper_torso_area = get_volume_result(side_rcnn_mask, side_image, upper_torso_bbox[1], upper_torso_bbox[0], upper_torso_bbox[3], upper_torso_bbox[2]) # Upper torso volume
    full_side_body_area = (side_rcnn_mask > 0).sum()
    # print(f"Thigh area: {thigh_area}")
    # print(f"Torso area: {torso_area}")
    # print(f"Lower torso area: {lower_torso_area}")
    # print(f"Upper torso area: {upper_torso_area}")
    results_dict['thigh_area'] = thigh_area
    results_dict['torso_area'] = torso_area
    results_dict['lower_torso_area'] = lower_torso_area
    results_dict['upper_torso_area'] = upper_torso_area
    results_dict['full_side_body_area'] = full_side_body_area

    # # calculate ratios
    results_dict['thigh_normalised'] = thigh_area / side_body_length
    results_dict['torso_normalised'] = torso_area / side_body_length
    results_dict['thigh_to_torso_ratio_normalised'] = results_dict['thigh_normalised'] / results_dict['torso_normalised']
    results_dict['thigh_to_torso_ratio'] = thigh_area / torso_area
    results_dict['upper_torso_normalised'] = upper_torso_area / side_body_length
    results_dict['lower_torso_normalised'] = lower_torso_area / side_body_length
    results_dict['upper_to_lower_torso_normalised_ratio'] =  results_dict['upper_torso_normalised'] / results_dict['lower_torso_normalised']
    results_dict['upper_to_lower_torso_ratio'] = upper_torso_area / lower_torso_area
    results_dict['shoulder_to_hip_ratio'] = results_dict['shoulder_width'] / results_dict['hip_width']
    results_dict['shoulder_to_waist_ratio'] = results_dict['shoulder_width'] / results_dict['waist_width']
    results_dict['waist_to_hip_ratio'] = results_dict['waist_width'] / results_dict['hip_width']
    results_dict['thigh_to_body_ratio'] = thigh_area / full_side_body_area
    results_dict['upper_torso_to_body_ratio'] = upper_torso_area / full_side_body_area
    results_dict['upper_torso_to_body_ratio'] = upper_torso_area / full_side_body_area

    # TODO: LOW PRIORITY: Not sure if we need this, but it was in the original code and select_body_shape uses it and requires an ID in a lot of places.
    # Could potentially remove it but will need to update select_body_shape too.
    results_dict['id'] = "1"

    results.append(results_dict)
    
    results_df = pd.DataFrame(results)
    return results_df