Spaces:
Build error
Build error
| from fastapi import FastAPI, UploadFile, File, HTTPException | |
| from fastapi.responses import JSONResponse | |
| import uvicorn | |
| import cv2 | |
| import numpy as np | |
| import joblib | |
| import mediapipe as mp | |
| import tempfile | |
| import os | |
| import pandas as pd | |
| import matplotlib.pyplot as plt | |
| from typing import Optional | |
| # MediaPipe setup | |
| mp_pose = mp.solutions.pose | |
| mp_drawing = mp.solutions.drawing_utils | |
| pose = mp_pose.Pose() | |
| # Load model and mappings | |
| model = joblib.load("MediaPipe_Model.pkl") | |
| label_to_pose_name = { | |
| 0: 'adho mukha svanasana', | |
| 1: 'adho mukha vriksasana', | |
| 2: 'agnistambhasana', 3: 'ananda balasana', 4: 'anantasana', 5: 'anjaneyasana', 6: 'ardha bhekasana', 7: 'ardha chandrasana', 8: 'ardha matsyendrasana', 9: 'ardha pincha mayurasana', 10: 'ardha uttanasana', 11: 'ashtanga namaskara', 12: 'astavakrasana', 13: 'baddha konasana', 14: 'bakasana', 15: 'balasana', 16: 'bhairavasana', 17: 'bharadvajasana i', 18: 'bhekasana', 19: 'bhujangasana', 20: 'bhujapidasana', 21: 'bitilasana', 22: 'camatkarasana', 23: 'chakravakasana', 24: 'chaturanga dandasana', 25: 'dandasana', 26: 'dhanurasana', 27: 'durvasasana', 28: 'dwi pada viparita dandasana', 29: 'eka pada koundinyanasana i', 30: 'eka pada koundinyanasana ii', 31: 'eka pada rajakapotasana', 32: 'eka pada rajakapotasana ii', 33: 'ganda bherundasana', 34: 'garbha pindasana', 35: 'garudasana', 36: 'gomukhasana', 37: 'halasana', 38: 'hanumanasana', 39: 'janu sirsasana', 40: 'kapotasana', 41: 'krounchasana', 42: 'kurmasana', 43: 'lolasana', 44: 'makara adho mukha svanasana', 45: 'makarasana', 46: 'malasana', 47: 'marichyasana i', 48: 'marichyasana iii', 49: 'marjaryasana', 50: 'matsyasana', 51: 'mayurasana', 52: 'natarajasana', 53: 'padangusthasana', 54: 'padmasana', 55: 'parighasana', 56: 'paripurna navasana', 57: 'parivrtta janu sirsasana', 58: 'parivrtta parsvakonasana', 59: 'parivrtta trikonasana', 60: 'parsva bakasana', 61: 'parsvottanasana', 62: 'pasasana', 63: 'paschimottanasana', 64: 'phalakasana', 65: 'pincha mayurasana', 66: 'prasarita padottanasana', 67: 'purvottanasana', 68: 'salabhasana', 69: 'salamba bhujangasana', 70: 'salamba sarvangasana', 71: 'salamba sirsasana', 72: 'savasana', 73: 'setu bandha sarvangasana', 74: 'simhasana', 75: 'sukhasana', 76: 'supta baddha konasana', 77: 'supta matsyendrasana', 78: 'supta padangusthasana', 79: 'supta virasana', 80: 'tadasana', 81: 'tittibhasana', 82: 'tolasana', 83: 'tulasana', 84: 'upavistha konasana', 85: 'urdhva dhanurasana', 86: 'urdhva hastasana', 87: 'urdhva mukha svanasana', 88: 'urdhva prasarita eka padasana', 89: 'ustrasana', 90: 'utkatasana', 91: 'uttana shishosana', 92: 'uttanasana', 93: 'utthita ashwa sanchalanasana', 94: 'utthita hasta padangustasana', 95: 'utthita parsvakonasana', 96: 'utthita trikonasana', 97: 'vajrasana', 98: 'vasisthasana', 99: 'viparita karani', 100: 'virabhadrasana i', 101: 'virabhadrasana ii', 102: 'virabhadrasana iii', 103: 'virasana', 104: 'vriksasana', 105: 'vrischikasana', 106: 'yoganidrasana' | |
| } | |
| # CSV file containing image links | |
| csv_path = r"C:\Users\Hp\Desktop\YOGA\pose_links.csv" | |
| # Reference angles for feedback | |
| reference_angles = { | |
| "adho mukha svanasana": { | |
| "left_elbow": 150, | |
| "right_elbow": 150, | |
| "left_hip": 120, | |
| "right_hip": 120, | |
| "neck": 90, | |
| "shoulders": 120, | |
| # Add more joints as necessary | |
| }, | |
| "adho mukha vriksasana": { | |
| "left_elbow": 180, | |
| "right_elbow": 180, | |
| "neck": 90, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "agnistambhasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "left_hip": 90, | |
| "right_hip": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "ananda balasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "left_hip": 90, | |
| "right_hip": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "anantasana": { | |
| "left_leg": 90, # Leg extended upwards | |
| "right_leg": 0, # Bent leg support | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "anjaneyasana": { | |
| "left_knee": 90, | |
| "right_knee": 180, | |
| "left_hip": 90, | |
| "right_hip": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "ardha bhekasana": { | |
| "left_leg": 90, | |
| "right_leg": 0, | |
| "left_hip": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "ardha chandrasana": { | |
| "left_leg": 90, | |
| "right_leg": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "ardha matsyendrasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "left_hip": 60, | |
| "right_hip": 60, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "ardha pincha mayurasana": { | |
| "left_elbow": 150, | |
| "right_elbow": 150, | |
| "neck": 90, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "ardha uttanasana": { | |
| "left_knee": 180, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "ashtanga namaskara": { | |
| "left_elbow": 90, | |
| "right_elbow": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "astavakrasana": { | |
| "left_leg": 90, | |
| "right_leg": 90, | |
| "left_hip": 45, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "baddha konasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "left_hip": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "bakasana": { | |
| "left_elbow": 90, | |
| "right_elbow": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "balasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "left_hip": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "bhairavasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "left_hip": 60, | |
| "right_hip": 60, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "bharadvajasana i": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "left_hip": 60, | |
| "right_hip": 60, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "bhekasana": { | |
| "left_leg": 90, | |
| "right_leg": 0, | |
| "left_hip": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "bhujangasana": { | |
| "left_elbow": 120, | |
| "right_elbow": 120, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "bhujapidasana": { | |
| "left_elbow": 90, | |
| "right_elbow": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "bitilasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "camatkarasana": { | |
| "left_leg": 90, | |
| "right_leg": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "chakravakasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "chaturanga dandasana": { | |
| "left_elbow": 90, | |
| "right_elbow": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "dandasana": { | |
| "left_knee": 180, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "dhanurasana": { | |
| "left_leg": 90, | |
| "right_leg": 90, | |
| "left_hip": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "durvasasana": { | |
| "left_leg": 90, | |
| "right_leg": 90, | |
| "left_hip": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "dwi pada viparita dandasana": { | |
| "left_knee": 180, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "eka pada koundinyanasana i": { | |
| "left_leg": 90, | |
| "right_leg": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "eka pada koundinyanasana ii": { | |
| "left_leg": 90, | |
| "right_leg": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "eka pada rajakapotasana": { | |
| "left_knee": 90, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "eka pada rajakapotasana ii": { | |
| "left_knee": 90, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "ganda bherundasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "garbha pindasana": { | |
| "left_leg": 90, | |
| "right_leg": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "garudasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "gomukhasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "halasana": { | |
| "left_knee": 180, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "hanumanasana": { | |
| "left_leg": 90, | |
| "right_leg": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "janu sirsasana": { | |
| "left_knee": 90, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "kapotasana": { | |
| "left_knee": 90, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "krounchasana": { | |
| "left_leg": 90, | |
| "right_leg": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "kurmasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "lolasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "makara adho mukha svanasana": { | |
| "left_elbow": 150, | |
| "right_elbow": 150, | |
| "neck": 90, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "makarasana": { | |
| "left_elbow": 120, | |
| "right_elbow": 120, | |
| "neck": 0, | |
| "hip": 180, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "malasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "marichyasana i": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "marichyasana iii": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "marjaryasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "matsyasana": { | |
| "left_knee": 90, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "mayurasana": { | |
| "left_elbow": 90, | |
| "right_elbow": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "natarajasana": { | |
| "left_leg": 90, | |
| "right_leg": 0, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "padangusthasana": { | |
| "left_knee": 180, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "padmasana": { | |
| "left_elbow": 90, | |
| "right_elbow": 90, | |
| # Add more joints | |
| }, | |
| "parighasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "paripurna navasana": { | |
| "left_knee": 180, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "parivrtta janu sirsasana": { | |
| "left_knee": 90, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "parivrtta parsvakonasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "parivrtta trikonasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "parsva bakasana": { | |
| "left_elbow": 90, | |
| "right_elbow": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "parsvottanasana": { | |
| "left_knee": 180, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "pasasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "paschimottanasana": { | |
| "left_knee": 180, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "phalakasana": { | |
| "left_elbow": 90, | |
| "right_elbow": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "pincha mayurasana": { | |
| "left_elbow": 150, | |
| "right_elbow": 150, | |
| "neck": 90, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "prasarita padottanasana": { | |
| "left_knee": 180, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "purvottanasana": { | |
| "left_knee": 180, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "salabhasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "salamba bhujangasana": { | |
| "left_elbow": 120, | |
| "right_elbow": 120, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "salamba sarvangasana": { | |
| "left_knee": 180, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "salamba sirsasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "savasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "setu bandha sarvangasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "simhasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "sukhasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "supta baddha konasana": { | |
| "left_knee": 90, | |
| "right_knee": 90, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "supta matsyendrasana": { | |
| "left_knee": 90, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| }, | |
| "supta matsyasana": { | |
| "left_knee": 90, | |
| "right_knee": 180, | |
| "neck": 0, | |
| "shoulders": 120, | |
| # Add more joints | |
| } | |
| } | |
| # Initialize FastAPI | |
| app = FastAPI() | |
| def calculate_angle(a, b, c): | |
| """ | |
| Calculate the angle between three points. | |
| """ | |
| ba = np.array([a[0] - b[0], a[1] - b[1]]) | |
| bc = np.array([c[0] - b[0], c[1] - b[1]]) | |
| cosine_angle = np.dot(ba, bc) / (np.linalg.norm(ba) * np.linalg.norm(bc)) | |
| angle = np.arccos(np.clip(cosine_angle, -1.0, 1.0)) | |
| return np.degrees(angle) | |
| def extract_angles(landmarks): | |
| """ | |
| Extracts angles between key body points using Mediapipe landmarks. | |
| Parameters: | |
| landmarks: A list of Mediapipe landmarks. | |
| Returns: | |
| A dictionary of angles with body parts as keys. | |
| """ | |
| angles = {} | |
| # Calculate angles for left and right arms | |
| angles["left_elbow"] = calculate_angle( | |
| [landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].x, | |
| landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].y], | |
| [landmarks[mp_pose.PoseLandmark.LEFT_ELBOW.value].x, | |
| landmarks[mp_pose.PoseLandmark.LEFT_ELBOW.value].y], | |
| [landmarks[mp_pose.PoseLandmark.LEFT_WRIST.value].x, | |
| landmarks[mp_pose.PoseLandmark.LEFT_WRIST.value].y] | |
| ) | |
| angles["right_elbow"] = calculate_angle( | |
| [landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value].x, | |
| landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value].y], | |
| [landmarks[mp_pose.PoseLandmark.RIGHT_ELBOW.value].x, | |
| landmarks[mp_pose.PoseLandmark.RIGHT_ELBOW.value].y], | |
| [landmarks[mp_pose.PoseLandmark.RIGHT_WRIST.value].x, | |
| landmarks[mp_pose.PoseLandmark.RIGHT_WRIST.value].y] | |
| ) | |
| # Calculate angles for left and right knees | |
| angles["left_knee"] = calculate_angle( | |
| [landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].x, | |
| landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].y], | |
| [landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value].x, | |
| landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value].y], | |
| [landmarks[mp_pose.PoseLandmark.LEFT_ANKLE.value].x, | |
| landmarks[mp_pose.PoseLandmark.LEFT_ANKLE.value].y] | |
| ) | |
| angles["right_knee"] = calculate_angle( | |
| [landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value].x, | |
| landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value].y], | |
| [landmarks[mp_pose.PoseLandmark.RIGHT_KNEE.value].x, | |
| landmarks[mp_pose.PoseLandmark.RIGHT_KNEE.value].y], | |
| [landmarks[mp_pose.PoseLandmark.RIGHT_ANKLE.value].x, | |
| landmarks[mp_pose.PoseLandmark.RIGHT_ANKLE.value].y] | |
| ) | |
| # Calculate the neck angle | |
| angles["neck"] = calculate_angle( | |
| [landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].x, | |
| landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].y], | |
| [landmarks[mp_pose.PoseLandmark.NOSE.value].x, | |
| landmarks[mp_pose.PoseLandmark.NOSE.value].y], | |
| [landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value].x, | |
| landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value].y] | |
| ) | |
| # Calculate hip and shoulder angles | |
| angles["left_hip"] = calculate_angle( | |
| [landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].x, | |
| landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].y], | |
| [landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].x, | |
| landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].y], | |
| [landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value].x, | |
| landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value].y] | |
| ) | |
| angles["right_hip"] = calculate_angle( | |
| [landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value].x, | |
| landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value].y], | |
| [landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value].x, | |
| landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value].y], | |
| [landmarks[mp_pose.PoseLandmark.RIGHT_KNEE.value].x, | |
| landmarks[mp_pose.PoseLandmark.RIGHT_KNEE.value].y] | |
| ) | |
| angles["left_shoulder"] = calculate_angle( | |
| [landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].x, | |
| landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].y], | |
| [landmarks[mp_pose.PoseLandmark.NOSE.value].x, | |
| landmarks[mp_pose.PoseLandmark.NOSE.value].y], | |
| [landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value].x, | |
| landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value].y] | |
| ) | |
| angles["right_shoulder"] = calculate_angle( | |
| [landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value].x, | |
| landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value].y], | |
| [landmarks[mp_pose.PoseLandmark.NOSE.value].x, | |
| landmarks[mp_pose.PoseLandmark.NOSE.value].y], | |
| [landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].x, | |
| landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].y] | |
| ) | |
| return angles | |
| def get_reference_image_link(predicted_pose: str) -> Optional[str]: | |
| """ | |
| Get the reference image link for the given predicted pose from the text file. | |
| """ | |
| text_file_path = "pose_links.txt" # Update with the correct path | |
| try: | |
| with open(text_file_path, "r") as f: | |
| lines = f.readlines() | |
| for line in lines: | |
| parts = line.strip().split(",") # Split by comma | |
| if len(parts) != 2: # Validate the format | |
| continue | |
| pose_name, image_link = parts[0].strip().lower(), parts[1].strip() | |
| if pose_name == predicted_pose.lower(): | |
| return image_link | |
| return None # Return None if no match found | |
| except FileNotFoundError: | |
| raise HTTPException(status_code=500, detail="Text file for pose links not found") | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=f"Error reading text file: {str(e)}") | |
| def read_root(): | |
| return {"message": "Yoga pose app"} | |
| async def predict_pose(file: UploadFile = File(...)): | |
| """ | |
| Predict the yoga pose and provide feedback. | |
| """ | |
| try: | |
| # Save uploaded file to a temporary location | |
| with tempfile.NamedTemporaryFile(delete=False) as tmp: | |
| tmp.write(await file.read()) | |
| temp_image_path = tmp.name | |
| # Read and process the image | |
| image = cv2.imread(temp_image_path) | |
| if image is None: | |
| raise HTTPException(status_code=400, detail="Invalid image file") | |
| image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) | |
| results = pose.process(image_rgb) | |
| # Check if pose landmarks are detected | |
| if not results.pose_landmarks: | |
| raise HTTPException(status_code=400, detail="No pose detected") | |
| # Extract keypoints and predict pose | |
| landmarks = results.pose_landmarks.landmark | |
| keypoints = [coord for landmark in landmarks for coord in (landmark.x, landmark.y, landmark.z)] | |
| predicted_label = model.predict([keypoints])[0] | |
| predicted_pose = label_to_pose_name.get(predicted_label, "Unknown Pose") | |
| # Provide feedback based on angles | |
| angles = extract_angles(landmarks) | |
| feedback = [] | |
| if predicted_pose in reference_angles: | |
| for joint, ref_angle in reference_angles[predicted_pose].items(): | |
| user_angle = angles.get(joint, None) | |
| if user_angle and abs(user_angle - ref_angle) > 10: | |
| feedback.append(f"Adjust your {joint}, off by {abs(user_angle - ref_angle):.2f}°") | |
| feedback_message = feedback if feedback else ["Great job! Your pose matches the reference."] | |
| # Visualize pose landmarks | |
| mp_drawing.draw_landmarks(image_rgb, results.pose_landmarks, mp_pose.POSE_CONNECTIONS) | |
| visualization_path = f"{tempfile.gettempdir()}/visualization.jpg" | |
| plt.figure(figsize=(10, 10)) | |
| plt.imshow(image_rgb) | |
| plt.axis("off") | |
| plt.savefig(visualization_path) | |
| plt.close() | |
| # Get reference image link | |
| reference_image_link = get_reference_image_link(predicted_pose) | |
| # Clean up temporary files | |
| os.remove(temp_image_path) | |
| return { | |
| "predicted_pose": predicted_pose, | |
| "feedback": feedback_message, | |
| "visualization": visualization_path, | |
| "reference_image_link": reference_image_link | |
| } | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| if __name__ == "__main__": | |
| uvicorn.run(app, host="127.0.0.1", port=7860, reload=True) | |