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()