Yoga Pose Web App

sample of webapp

Read Me


# README.md

# Yoga Pose Classifier

This is a simple web application built with Streamlit for classifying yoga poses from uploaded images. The application uses a pre-trained deep learning model to predict the yoga pose in the uploaded image.

### Features

- Upload an image of a yoga pose.
- Display the uploaded image.
- Predict the pose in the image.
- Visualize prediction results as a bar plot.
 
Must have ultalytics installed
pip install ultalytics

### Command
streamlit run app.py

# ctrl-c to stop the program

 

Libraries and Functions


import os
import numpy as np
import pickle
import pandas as pd

import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.image import load_img, img_to_array
from tensorflow.keras.layers import Lambda, Input
from tensorflow.keras.models import Model
from tensorflow.keras.applications.resnet_v2 import ResNet50V2, preprocess_input as resnet_preprocess
from tensorflow.keras.applications.densenet import DenseNet121, preprocess_input as densenet_preprocess
from ultralytics import YOLO
from sklearn.preprocessing import LabelEncoder

# Get current working directory
current_path = os.getcwd()

# Path to yoga pose categories file
pose_category_path = os.path.join(current_path, 'static/poses_category.pkl')

# Load predictor model
predictor_model_transfer = load_model(r'static/resnet_finetuned_model3.h5')
print("Weights loaded")

predictor_model_low = load_model(r'static/resnet_finetuned_model2.h5')
print("Weights loaded")

predictor_model_simple= load_model(r'static/model3_assign2.h5')
print("Weights loaded")

predictor_pose_est= load_model(r'static/yoga_pose_classifier_pd4.h5')
print("Weights loaded")

# Load pose categories
with open(pose_category_path, 'rb') as handle:
    poses = pickle.load(handle)

# Input shape for images
input_shape = (224, 224, 3)
input_layer = Input(shape=input_shape)


print("Models loaded")




def predictor_transfer(img_path):
    """
    Function to predict Yoga Pose from an image.
    Args:
        img_path (str): Path to the input image.
    Returns:
        pandas.DataFrame: DataFrame containing predicted Yoga Poses and their corresponding confidence scores.
    """
    # Load image and preprocess
    img = load_img(img_path, target_size=(224, 224))
    img = img_to_array(img)
    img = np.expand_dims(img, axis=0)
    
    # Predict yoga poses
    prediction_transfer = predictor_model_transfer.predict(img) * 100
    prediction_transfer  = pd.DataFrame(np.round(prediction_transfer, 1), columns=poses).transpose()
    prediction_transfer.columns = ['values']
    prediction_transfer  = prediction_transfer.nlargest(5, 'values')
    prediction_transfer  = prediction_transfer.reset_index()
    prediction_transfer.columns = ['name', 'values']

    return prediction_transfer 

def predictor_simple(img_path):
    """
    Function to predict Yoga Pose from an image.

    Args:
        img_path (str): Path to the input image.

    Returns:
        pandas.DataFrame: DataFrame containing predicted Yoga Poses and their corresponding confidence scores.
    """
    # Load image and preprocess
    img = load_img(img_path, target_size=(224, 224))
    img = img_to_array(img)
    img = np.expand_dims(img, axis=0)

    # Predict yoga poses
    prediction = predictor_model_simple.predict(img) * 100
    prediction = pd.DataFrame(np.round(prediction, 1), columns=poses).transpose()
    prediction.columns = ['values']
    prediction = prediction.nlargest(5, 'values')
    prediction = prediction.reset_index()
    prediction.columns = ['name', 'values']

    return prediction

def predictor_low_acc(img_path):
    """
    Function to predict Yoga Pose from an image.

    Args:
        img_path (str): Path to the input image.

    Returns:
        pandas.DataFrame: DataFrame containing predicted Yoga Poses and their corresponding confidence scores.
    """
    # Load image and preprocess
    img = load_img(img_path, target_size=(224, 224))
    img = img_to_array(img)
    img = np.expand_dims(img, axis=0)

    # Predict yoga poses
    prediction = predictor_model_low.predict(img) * 100
    prediction = pd.DataFrame(np.round(prediction, 1), columns=poses).transpose()
    prediction.columns = ['values']
    prediction = prediction.nlargest(5, 'values')
    prediction = prediction.reset_index()
    prediction.columns = ['name', 'values']

    return prediction

############################# Pose Estimation ##################

model_yolo = YOLO("yolo11n-pose.pt") 
model_nn = load_model("static/yoga_pose_classifier_pd4.h5")  # Update with actual model path

# Function to extract keypoints from a new image

# Load class names from pickle file
pickle_file = "static/poses_category.pkl"  # Update with actual path
with open(pickle_file, "rb") as f:
    class_names = pickle.load(f)  # Load class names dictionary or list

# Ensure class_names is a list
if isinstance(class_names, dict):
    class_names = list(class_names.values())  # Convert dictionary to list

 
# Function to extract keypoints from a test image
def extract_keypoints_from_image(img_path, expected_num_keypoints=196):
    results = model_yolo(img_path)
    for result in results:
        if result.keypoints is not None and len(result.keypoints.xy.cpu().numpy()) > 0:
            keypoints = result.keypoints.xy.cpu().numpy().flatten()

            # Ensure the keypoints have the correct shape (pad with zeros if needed)
            if len(keypoints) < expected_num_keypoints:
                keypoints = np.pad(keypoints, (0, expected_num_keypoints - len(keypoints)), mode='constant')
            
            return keypoints
    return None  # Return None if no pose is detected

# Function to predict yoga pose and return a DataFrame for bar plot
def predict_yoga_pose(img_path):
    new_keypoints = extract_keypoints_from_image(img_path)

    if new_keypoints is not None:
        new_keypoints = np.array(new_keypoints).reshape(1, -1)  # Reshape for model input

        if new_keypoints.shape[1] == model_nn.input_shape[1]:
            pose_probs = model_nn.predict(new_keypoints)[0]  # Get class probabilities
            
            # Create a DataFrame for visualization
            prediction_df = pd.DataFrame({
                "name": class_names,  # Class names from pickle
                "values": pose_probs * 100  # Convert to percentage
            })

# Get top 5 predictions
            top_5_predictions = prediction_df.sort_values("values", ascending=False).head(5)

            return top_5_predictions
            
 

Application


import streamlit as st
import os
import logging
import matplotlib.pyplot as plt
import seaborn as sns
from PIL import Image
from helper import *

# Set seaborn style
sns.set()

# Configure logging
logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', level=logging.INFO)

def save_uploaded_file(uploaded_file):
    """
    Save the uploaded file to the 'uploaded' directory.

    Args:
        uploaded_file (File): Uploaded file object.

    Returns:
        int: Status code indicating success (1) or failure (0).
    """
    try:
        with open(os.path.join('uploaded', uploaded_file.name), 'wb') as f:
            f.write(uploaded_file.getbuffer())
        return 1    
    except:
        return 0        

def main():
    """
    Main function to run the Streamlit app.
    """
    # Set app title
    st.title('Yoga Pose Classifier')
    
    option = st.selectbox(
    "What model do you want to use?",
    ("Transfer Learning Imagenet", "Simple CNN", "Low accuracy Transfer Learning", "Ultralytics Pose Estimation Preprocessing"),
    )

    st.write("You selected:", option)
    print(option)

    # File uploader
    uploaded_file = st.file_uploader("Upload Image")

    if uploaded_file is not None:
        logging.info("File uploaded: %s", uploaded_file.name)
        # Save the uploaded file
        if save_uploaded_file(uploaded_file):
            # Display the uploaded image
            display_image = Image.open(uploaded_file)
            display_image = display_image.resize((224, 224))  # Resize image
            st.image(display_image)
            if option == 'Transfer Learning Imagenet':
                # Make prediction using the uploaded image
                prediction_transfer = predictor_transfer(os.path.join('uploaded', uploaded_file.name))
                logging.info("Prediction: %s", prediction_transfer)
                st.markdown('**Predictions**')
                       # Display predictions as bar plot
                fig, ax = plt.subplots()
                ax = sns.barplot(y='name', x='values', data=prediction_transfer, 
                            order=prediction_transfer.sort_values('values', ascending=False).name)
                ax.set(xlabel='Confidence %', ylabel='Pose')
                st.pyplot(fig)
            if option == "Simple CNN":
                prediction_simple = predictor_simple(os.path.join('uploaded', uploaded_file.name))
                logging.info("Prediction: %s", prediction_simple)
                st.markdown('**Predictions**')
                       # Display predictions as bar plot
                fig, ax = plt.subplots()
                ax = sns.barplot(y='name', x='values', data=prediction_simple , 
                            order=prediction_simple.sort_values('values', ascending=False).name)
                ax.set(xlabel='Confidence %', ylabel='Pose')
                st.pyplot(fig)
            if option == "Low accuracy Transfer Learning":
                prediction_low = predictor_low_acc(os.path.join('uploaded', uploaded_file.name))
                logging.info("Prediction: %s", prediction_low)
                st.markdown('**Predictions**')
                       # Display predictions as bar plot
                fig, ax = plt.subplots()
                ax = sns.barplot(y='name', x='values', data=prediction_low , 
                            order=prediction_low.sort_values('values', ascending=False).name)
                ax.set(xlabel='Confidence %', ylabel='Pose')
                st.pyplot(fig)
                
            if option == "Ultralytics Pose Estimation Preprocessing":
                prediction_ultra = predict_yoga_pose(os.path.join('uploaded', uploaded_file.name))
                logging.info("Prediction: %s", prediction_ultra)
                st.markdown('**Predictions**')
                       # Display predictions as bar plot
                fig, ax = plt.subplots()
                ax = sns.barplot(y='name', x='values', data=prediction_ultra , 
                            order=prediction_ultra.sort_values('values', ascending=False).name)
                ax.set(xlabel='Confidence %', ylabel='Pose')
                st.pyplot(fig)
            
if __name__ == '__main__':
    main()