Spaces:
Sleeping
Sleeping
Niharmahesh
commited on
Update app.py
Browse files
app.py
CHANGED
@@ -2,109 +2,106 @@ import streamlit as st
|
|
2 |
import cv2
|
3 |
import numpy as np
|
4 |
import mediapipe as mp
|
5 |
-
import
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
}
|
25 |
|
26 |
# Initialize MediaPipe Hands
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
def
|
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 |
-
predictions[model_name] = (prediction, probability)
|
67 |
-
|
68 |
-
return predictions, results.multi_hand_landmarks[0]
|
69 |
-
|
70 |
-
def draw_hand_landmarks(image, hand_landmarks):
|
71 |
-
for landmark in hand_landmarks.landmark:
|
72 |
-
h, w, _ = image.shape
|
73 |
-
cx, cy = int(landmark.x * w), int(landmark.y * h)
|
74 |
-
cv2.circle(image, (cx, cy), 5, (0, 255, 0), -1)
|
75 |
-
return image
|
76 |
-
|
77 |
-
# Streamlit App
|
78 |
-
st.title("ASL Hand Shape Recognition App")
|
79 |
-
|
80 |
-
uploaded_file = st.file_uploader("Choose a hand image...", type=["jpg", "jpeg", "png"])
|
81 |
|
82 |
if uploaded_file is not None:
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
import cv2
|
3 |
import numpy as np
|
4 |
import mediapipe as mp
|
5 |
+
import joblib
|
6 |
+
import pandas as pd
|
7 |
+
from numpy.linalg import norm
|
8 |
+
|
9 |
+
# Function to load the Random Forest model
|
10 |
+
@st.cache_resource
|
11 |
+
def load_model():
|
12 |
+
try:
|
13 |
+
return joblib.load('best_random_forest_model.pkl')
|
14 |
+
except Exception as e:
|
15 |
+
st.error(f"Error loading model: {e}")
|
16 |
+
return None
|
17 |
+
|
18 |
+
# Load the model using the cached function
|
19 |
+
model = load_model()
|
20 |
+
|
21 |
+
# Ensure the model is loaded before proceeding
|
22 |
+
if model is None:
|
23 |
+
st.stop()
|
|
|
24 |
|
25 |
# Initialize MediaPipe Hands
|
26 |
+
@st.cache_resource
|
27 |
+
def load_mediapipe_model():
|
28 |
+
mp_hands = mp.solutions.hands
|
29 |
+
return mp_hands.Hands(static_image_mode=True, max_num_hands=1, min_detection_confidence=0.5)
|
30 |
+
|
31 |
+
hands = load_mediapipe_model()
|
32 |
+
mp_drawing = mp.solutions.drawing_utils
|
33 |
+
|
34 |
+
# Function to normalize landmarks
|
35 |
+
def normalize_landmarks(landmarks):
|
36 |
+
# Center the landmarks
|
37 |
+
center = np.mean(landmarks, axis=0)
|
38 |
+
landmarks_centered = landmarks - center
|
39 |
+
|
40 |
+
# Scale the landmarks to unit variance
|
41 |
+
std_dev = np.std(landmarks_centered, axis=0)
|
42 |
+
landmarks_normalized = landmarks_centered / std_dev
|
43 |
+
|
44 |
+
# Replace NaN values with 0 (in case of division by zero)
|
45 |
+
landmarks_normalized = np.nan_to_num(landmarks_normalized)
|
46 |
+
|
47 |
+
return landmarks_normalized
|
48 |
+
|
49 |
+
# Function to calculate angles between landmarks
|
50 |
+
def calculate_angles(landmarks):
|
51 |
+
angles = []
|
52 |
+
for i in range(20):
|
53 |
+
for j in range(i + 1, 21):
|
54 |
+
vector = landmarks[j] - landmarks[i]
|
55 |
+
angle_x = np.arccos(np.clip(vector[0] / norm(vector), -1.0, 1.0))
|
56 |
+
angle_y = np.arccos(np.clip(vector[1] / norm(vector), -1.0, 1.0))
|
57 |
+
angles.extend([angle_x, angle_y])
|
58 |
+
return angles
|
59 |
+
|
60 |
+
# Streamlit app
|
61 |
+
st.title("ASL Recognition App")
|
62 |
+
|
63 |
+
# Upload image using Streamlit's file uploader
|
64 |
+
uploaded_file = st.file_uploader("Upload an image of an ASL sign", type=["jpg", "jpeg", "png"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
|
66 |
if uploaded_file is not None:
|
67 |
+
try:
|
68 |
+
# Read the image
|
69 |
+
image = cv2.imdecode(np.frombuffer(uploaded_file.read(), np.uint8), cv2.IMREAD_COLOR)
|
70 |
+
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
|
71 |
+
|
72 |
+
# Process the image and find hand landmarks
|
73 |
+
results = hands.process(image_rgb)
|
74 |
+
|
75 |
+
if results.multi_hand_landmarks:
|
76 |
+
for hand_landmarks in results.multi_hand_landmarks:
|
77 |
+
# Draw landmarks on the image
|
78 |
+
mp_drawing.draw_landmarks(image, hand_landmarks, mp.solutions.hands.HAND_CONNECTIONS)
|
79 |
+
|
80 |
+
# Extract and normalize landmarks
|
81 |
+
landmarks = np.array([[lm.x, lm.y] for lm in hand_landmarks.landmark])
|
82 |
+
landmarks_normalized = normalize_landmarks(landmarks)
|
83 |
+
|
84 |
+
# Calculate angles using normalized landmarks
|
85 |
+
angles = calculate_angles(landmarks_normalized)
|
86 |
+
|
87 |
+
# Prepare input with feature names
|
88 |
+
angle_columns = [f'angle_{i}' for i in range(len(angles))]
|
89 |
+
angles_df = pd.DataFrame([angles], columns=angle_columns)
|
90 |
+
|
91 |
+
# Predict the alphabet
|
92 |
+
probabilities = model.predict_proba(angles_df)[0]
|
93 |
+
top_indices = np.argsort(probabilities)[::-1][:5]
|
94 |
+
top_probabilities = probabilities[top_indices]
|
95 |
+
top_classes = model.classes_[top_indices]
|
96 |
+
|
97 |
+
# Display the top 5 predictions
|
98 |
+
st.write("Top 5 Predicted Alphabets:")
|
99 |
+
for i in range(5):
|
100 |
+
st.write(f"{top_classes[i]}: {top_probabilities[i]:.2f}")
|
101 |
+
|
102 |
+
# Display the image with landmarks
|
103 |
+
st.image(image, caption="Processed Image with Landmarks", use_column_width=True)
|
104 |
+
else:
|
105 |
+
st.write("No hands detected. Please try another image.")
|
106 |
+
except Exception as e:
|
107 |
+
st.error(f"Error processing image: {e}")
|