File size: 9,538 Bytes
d1dd6cd
 
fb80e43
8d50fbe
fb80e43
 
6e2e2cd
6a904bc
6e2e2cd
 
9c2dabf
7efdf9a
 
9c2dabf
6e2e2cd
181e040
 
 
 
 
 
 
11d8417
 
f869fe7
 
 
6321d7c
 
11d8417
 
 
181e040
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59d5d56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181e040
59d5d56
9c2dabf
59d5d56
 
8197e9c
 
59d5d56
 
 
 
 
 
 
 
 
c4193b8
59d5d56
 
 
9c2dabf
59d5d56
 
 
 
 
 
 
9c2dabf
8197e9c
59d5d56
8197e9c
59d5d56
8197e9c
59d5d56
 
 
6eb2ab9
0bd21aa
3014d12
59d5d56
6321d7c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a029c01
6321d7c
a029c01
6321d7c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f8d143b
 
d155fb5
 
6321d7c
 
 
 
 
 
 
1fe2250
c64cdf0
6e2e2cd
 
 
 
 
2cf1016
6e2e2cd
2cf1016
6e2e2cd
 
61baa81
3014d12
 
1fe2250
 
6321d7c
 
 
 
 
 
 
3014d12
c6c8746
 
916db9a
 
 
a4d7cf8
11d8417
2eebe1a
916db9a
0a2e7a8
3014d12
ae96590
97b0cf9
6e2e2cd
c6c8746
ea79774
c6c8746
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
import gradio as gr

import math
import time
import mediapipe as mp

import cv2
from PIL import Image
import numpy as np
import datetime
import copy
from openpose import util
from openpose.body import Body
import matplotlib.pyplot as plt

    
mp_pose = mp.solutions.pose

pose = mp_pose.Pose(static_image_mode=True, min_detection_confidence=0.3, model_complexity=2)

mp_drawing = mp.solutions.drawing_utils 

def change_example(choice):
    if choice == "plank":
        return gr.Image.update(value="examples/plank.jpg")
    elif choice == "downdog":
        return gr.update(value="examples/downdog.jpg")
    elif choice == "tree":
        return gr.update(value="examples/tree.jpg")
    else:
        return gr.update(visible=False)

def points(image):
    results = pose.process(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
    image_height, image_width, _ = image.shape

    img_copy = image.copy()

    if results.pose_landmarks:
        mp_drawing.draw_landmarks(image=img_copy, landmark_list=results.pose_landmarks, connections=mp_pose.POSE_CONNECTIONS)
       
        img = plt.figure(figsize = [10, 10])

        plt.axis('off')
        plt.imshow(img_copy[:,:,::-1])
        return img

    else:
        return gr.Image("examples/Error.png")

def landmarks(image):
    results = pose.process(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
    height, width, _ = image.shape

    landmarks = []

    if results.pose_landmarks:          
        for landmark in results.pose_landmarks.landmark:            
            landmarks.append((int(landmark.x * width), int(landmark.y * height),
                                  (landmark.z * width)))
    return landmarks 

def calculateAngle(landmark1, landmark2, landmark3):

    x1, y1, _ = landmark1
    x2, y2, _ = landmark2
    x3, y3, _ = landmark3

    angle = math.degrees(math.atan2(y3 - y2, x3 - x2) - math.atan2(y1 - y2, x1 - x2))
    
    if angle < 0:
        angle += 360
    if angle > 180:
        angle = 360 - angle
    
    return angle

def correct_plank(landmarks):
    recommendation = ""
    result = ""
    left_knee_angle = calculateAngle(landmarks[mp_pose.PoseLandmark.LEFT_HIP.value],
                                     landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value],
                                     landmarks[mp_pose.PoseLandmark.LEFT_ANKLE.value])

    right_knee_angle = calculateAngle(landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value],
                                      landmarks[mp_pose.PoseLandmark.RIGHT_KNEE.value],
                                      landmarks[mp_pose.PoseLandmark.RIGHT_ANKLE.value])
    
    left_hip_angle = calculateAngle(landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value],
                                     landmarks[mp_pose.PoseLandmark.LEFT_HIP.value],
                                     landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value])

    right_hip_angle = calculateAngle(landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value],
                                      landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value],
                                      landmarks[mp_pose.PoseLandmark.RIGHT_KNEE.value])
    
    if (left_knee_angle>180 or left_knee_angle<170):
        recommendation = recommendation + "The left knee should be straight. "
    if (right_knee_angle>180 or right_knee_angle<170):
        recommendation = recommendation + "The right knee should be straight. "
    if ((left_hip_angle>180 or left_hip_angle<170) or (right_hip_angle>180 or right_hip_angle<170)):
        recommendation = recommendation + "The spine should be straight. "
    if recommendation == "":
        result = "Great! You are doing the exercise correctly"
    else:
        result = "Almost perfect, but \n"
    return result + recommendation    

def correct_dog(landmarks):
    recommendation = ""
    result = ""
    left_hip_angle = calculateAngle(landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value],
                                     landmarks[mp_pose.PoseLandmark.LEFT_HIP.value],
                                     landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value])

    right_hip_angle = calculateAngle(landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value],
                                      landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value],
                                      landmarks[mp_pose.PoseLandmark.RIGHT_KNEE.value])
    
    left_leg = calculateAngle(landmarks[mp_pose.PoseLandmark.LEFT_HIP.value],
                              landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value],
                              landmarks[mp_pose.PoseLandmark.LEFT_ANKLE.value])
    right_leg = calculateAngle(landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value],
                               landmarks[mp_pose.PoseLandmark.RIGHT_KNEE.value],
                               landmarks[mp_pose.PoseLandmark.RIGHT_ANKLE.value])
    
    right_hand = calculateAngle(landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value],
                                landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value],
                                landmarks[mp_pose.PoseLandmark.RIGHT_ELBOW.value])

    left_hand = calculateAngle(landmarks[mp_pose.PoseLandmark.LEFT_HIP.value],
                               landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value],
                               landmarks[mp_pose.PoseLandmark.LEFT_ELBOW.value])
    
    if (left_hip_angle>90 or right_hip_angle>90):
        recommendation += "The spine should be bent. "
    if not (170 < left_leg < 181 or 170 < right_leg < 181):
        recommendation = "Legs should be straight. "
    if not (170 < left_hand < 181 or 181 > right_hand > 170):
        recommendation = "Hands should be straight. "
    if recommendation == "":
        result = "Great! You are doing the exercise correctly"
    else:
        result = "Almost perfect, but \n"

    return result + recommendation

def correct_tree(landmarks):
    recommendation = ""
    result = ""
    left_hip_angle = calculateAngle(landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value],
                                     landmarks[mp_pose.PoseLandmark.LEFT_HIP.value],
                                     landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value])

    right_hip_angle = calculateAngle(landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value],
                                      landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value],
                                      landmarks[mp_pose.PoseLandmark.RIGHT_KNEE.value])
    
    left_leg = calculateAngle(
                                     landmarks[mp_pose.PoseLandmark.LEFT_HIP.value],
                                     landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value],
                                     landmarks[mp_pose.PoseLandmark.LEFT_ANKLE.value])
    right_leg = calculateAngle(
                                      landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value],
                                      landmarks[mp_pose.PoseLandmark.RIGHT_KNEE.value],
                                      landmarks[mp_pose.PoseLandmark.RIGHT_ANKLE.value])
    
    right_hand = calculateAngle(
                                      landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value],
                                      landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value],
                                     landmarks[mp_pose.PoseLandmark.RIGHT_ELBOW.value])

    left_hand = calculateAngle(
                                      landmarks[mp_pose.PoseLandmark.LEFT_HIP.value],
                                      landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value],
                                      landmarks[mp_pose.PoseLandmark.LEFT_ELBOW.value])
    
    
    #if (left_hand>90 or right_hand>90):
    #    recommendation += "Hands should be bent. "
    if not (((175 < right_leg < 181) and (left_leg < 100)) or ((175 < left_leg < 181) and (right_leg < 100))):
        recommendation = "One leg should be straight and another should be bent. "
    if recommendation == "":
        result = "Great! You are doing the exercise correctly"
    else:
        result = "Almost perfect, but \n"

    return result + recommendation

def detect(video, radio):
    video_clip = cv2.VideoCapture(video)
    frames = video_clip.get(cv2.CAP_PROP_FRAME_COUNT)
    
    i=0
    while(video_clip.isOpened()):
        is_read, frame = video_clip.read()
        image = frame
        if i == round(frames/2):
            image = frame
            break
        i+=1
    new_image = points(image)

    result = ""
    if radio == "plank":
        result = correct_plank(landmarks(image))
        
    if radio == "downdog":
        result = correct_dog(landmarks(image))

    if radio == "tree":
        result = correct_tree(landmarks(image))
        
    return new_image, result

with gr.Blocks() as demo:
    with gr.Row():
        with gr.Column():
            radio = gr.Radio(["plank", "downdog", "tree"], label="Choose the exercise")
            image1 = gr.Image("examples/Example.png")
            video = gr.Video(label="Upload video with exercise")
            check_btn = gr.Button(value="Let's go")
        with gr.Column():
            image = gr.Plot() 
            result = gr.Textbox()
    radio.change(fn=change_example, inputs=radio, outputs=image1)
    check_btn.click(detect, inputs=[video, radio], outputs=[image, result])
    
demo.launch()
    
            
#gr.Interface(
#    fn=detect,
#    inputs=gr.Video(label="Upload video with exercise"), 
#    outputs="image", 
#    title="Are you doing the exercise correct?"
#).launch()