Spaces:
Running
Running
import streamlit as st | |
import cv2 | |
import numpy as np | |
import mediapipe as mp | |
import joblib | |
import pandas as pd | |
from numpy.linalg import norm | |
# Function to load the Random Forest model | |
def load_model(): | |
try: | |
return joblib.load('best_random_forest_model.pkl') | |
except Exception as e: | |
st.error(f"Error loading model: {e}") | |
return None | |
# Load the model using the cached function | |
model = load_model() | |
# Ensure the model is loaded before proceeding | |
if model is None: | |
st.stop() | |
# Initialize MediaPipe Hands | |
def load_mediapipe_model(): | |
mp_hands = mp.solutions.hands | |
return mp_hands.Hands(static_image_mode=True, max_num_hands=1, min_detection_confidence=0.5) | |
hands = load_mediapipe_model() | |
mp_drawing = mp.solutions.drawing_utils | |
# Function to normalize landmarks | |
def normalize_landmarks(landmarks): | |
# Center the landmarks | |
center = np.mean(landmarks, axis=0) | |
landmarks_centered = landmarks - center | |
# Scale the landmarks to unit variance | |
std_dev = np.std(landmarks_centered, axis=0) | |
landmarks_normalized = landmarks_centered / std_dev | |
# Replace NaN values with 0 (in case of division by zero) | |
landmarks_normalized = np.nan_to_num(landmarks_normalized) | |
return landmarks_normalized | |
# Function to calculate angles between landmarks | |
def calculate_angles(landmarks): | |
angles = [] | |
for i in range(20): | |
for j in range(i + 1, 21): | |
vector = landmarks[j] - landmarks[i] | |
angle_x = np.arccos(np.clip(vector[0] / norm(vector), -1.0, 1.0)) | |
angle_y = np.arccos(np.clip(vector[1] / norm(vector), -1.0, 1.0)) | |
angles.extend([angle_x, angle_y]) | |
return angles | |
# Streamlit app | |
st.title("ASL Recognition App") | |
# Upload image using Streamlit's file uploader | |
uploaded_file = st.file_uploader("Upload an image of an ASL sign", type=["jpg", "jpeg", "png"]) | |
if uploaded_file is not None: | |
try: | |
# Read the image | |
image = cv2.imdecode(np.frombuffer(uploaded_file.read(), np.uint8), cv2.IMREAD_COLOR) | |
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) | |
# Process the image and find hand landmarks | |
results = hands.process(image_rgb) | |
if results.multi_hand_landmarks: | |
for hand_landmarks in results.multi_hand_landmarks: | |
# Draw landmarks on the image | |
mp_drawing.draw_landmarks(image, hand_landmarks, mp.solutions.hands.HAND_CONNECTIONS) | |
# Extract and normalize landmarks | |
landmarks = np.array([[lm.x, lm.y] for lm in hand_landmarks.landmark]) | |
landmarks_normalized = normalize_landmarks(landmarks) | |
# Calculate angles using normalized landmarks | |
angles = calculate_angles(landmarks_normalized) | |
# Prepare input with feature names | |
angle_columns = [f'angle_{i}' for i in range(len(angles))] | |
angles_df = pd.DataFrame([angles], columns=angle_columns) | |
# Predict the alphabet | |
probabilities = model.predict_proba(angles_df)[0] | |
top_indices = np.argsort(probabilities)[::-1][:5] | |
top_probabilities = probabilities[top_indices] | |
top_classes = model.classes_[top_indices] | |
# Display the top 5 predictions | |
st.write("Top 5 Predicted Alphabets:") | |
for i in range(5): | |
st.write(f"{top_classes[i]}: {top_probabilities[i]:.2f}") | |
# Display the image with landmarks | |
st.image(image, caption="Processed Image with Landmarks", use_column_width=True) | |
else: | |
st.write("No hands detected. Please try another image.") | |
except Exception as e: | |
st.error(f"Error processing image: {e}") |