Niharmahesh commited on
Commit
d1c5054
1 Parent(s): ec7574f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -93
app.py CHANGED
@@ -1,7 +1,11 @@
1
  import streamlit as st
2
- from model import load_model, process_and_predict
3
- from landmarks import normalize_landmarks, calculate_angles
4
- from visualization import plot_hand_landmarks
 
 
 
 
5
  import os
6
 
7
  st.set_page_config(layout="wide")
@@ -11,100 +15,83 @@ all_alphabets = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
11
  excluded_alphabets = 'DMNPTUVXZ'
12
  working_alphabets = ''.join(set(all_alphabets) - set(excluded_alphabets))
13
 
14
- # README content
15
- readme_content = f"""
16
- ## How it works
17
-
18
- This ASL Recognition App uses image processing and machine learning to recognize American Sign Language (ASL) hand signs.
19
-
20
- 1. **Image Upload**: Users can upload an image of an ASL hand sign.
21
- 2. **Hand Detection**: The app uses MediaPipe to detect hand landmarks in the image.
22
- 3. **Feature Extraction**: Angles between hand landmarks are calculated and normalized.
23
- 4. **Prediction**: A Random Forest model predicts the ASL sign based on the extracted features.
24
- 5. **Visualization**: The app displays the detected hand landmarks and top predictions.
25
-
26
- ### Supported Alphabets
27
-
28
- The app currently works for the following ASL alphabets:
29
- {', '.join(working_alphabets)}
30
-
31
- The app does not support or may not work correctly for:
32
- {', '.join(excluded_alphabets)}
33
-
34
- Note: The model's performance may vary and is subject to improvement.
35
-
36
- The "View Hand Landmarks" tab allows users to see hand landmarks for pre-loaded ASL signs.
37
- """
38
-
39
- # Load the model
40
  model = load_model()
41
 
42
  # Ensure the model is loaded before proceeding
43
  if model is None:
44
  st.stop()
45
 
46
- # Streamlit app
47
- st.title("ASL Recognition App")
48
-
49
- # Display README content
50
- st.sidebar.markdown(readme_content)
51
-
52
- # Create tabs for different functionalities
53
- tab1, tab2 = st.tabs(["Predict ASL Sign", "View Hand Landmarks"])
54
-
55
- with tab1:
56
- st.header("Predict ASL Sign")
57
- uploaded_file = st.file_uploader("Upload an image of an ASL sign", type=["jpg", "jpeg", "png"])
58
-
59
- if uploaded_file is not None:
60
- try:
61
- image = cv2.imdecode(np.frombuffer(uploaded_file.read(), np.uint8), 1)
62
- if image is not None:
63
- col1, col2 = st.columns(2)
64
- with col1:
65
- st.image(image, caption="Uploaded Image", use_column_width=True)
66
-
67
- probabilities, landmarks = process_and_predict(image)
68
-
69
- if probabilities is not None and landmarks is not None:
70
- with col2:
71
- st.subheader("Top 5 Predictions:")
72
- top_indices = np.argsort(probabilities)[::-1][:5]
73
- for i in top_indices:
74
- st.write(f"{model.classes_[i]}: {probabilities[i]:.2f}")
75
-
76
- fig = plot_hand_landmarks(landmarks, "Detected Hand Landmarks")
77
- st.pyplot(fig)
78
- else:
79
- st.write("No hand detected in the image.")
80
- else:
81
- st.error("Failed to load the image. The file might be corrupted.")
82
- except Exception as e:
83
- st.error(f"An error occurred while processing the image: {str(e)}")
84
-
85
- with tab2:
86
- st.header("View Hand Landmarks")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
- selected_alphabets = st.multiselect("Select alphabets to view landmarks:", list(working_alphabets))
89
-
90
- if selected_alphabets:
91
- cols = st.columns(4) # 4 columns for smaller images
92
- for idx, alphabet in enumerate(selected_alphabets):
93
- with cols[idx % 4]:
94
- image_path = os.path.join('asl test set', f'{alphabet.lower()}.jpeg')
95
- if os.path.exists(image_path):
96
- try:
97
- image = cv2.imread(image_path)
98
- if image is not None:
99
- probabilities, landmarks = process_and_predict(image)
100
- if landmarks is not None:
101
- fig = plot_hand_landmarks(landmarks, f"Hand Landmarks for {alphabet}")
102
- st.pyplot(fig)
103
- else:
104
- st.error(f"No hand detected for {alphabet}")
105
- else:
106
- st.error(f"Failed to load image for {alphabet}")
107
- except Exception as e:
108
- st.error(f"Error processing image for {alphabet}")
109
- else:
110
- st.error(f"Image not found for {alphabet}")
 
1
  import streamlit as st
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
+ import matplotlib.pyplot as plt
9
  import os
10
 
11
  st.set_page_config(layout="wide")
 
15
  excluded_alphabets = 'DMNPTUVXZ'
16
  working_alphabets = ''.join(set(all_alphabets) - set(excluded_alphabets))
17
 
18
+ # Function to load the Random Forest model
19
+ @st.cache_resource
20
+ def load_model():
21
+ """Load the Random Forest model from a file."""
22
+ try:
23
+ return joblib.load('best_random_forest_model.pkl')
24
+ except Exception as e:
25
+ st.error(f"Error loading model: {e}")
26
+ return None
27
+
28
+ # Load the model using the cached function
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  model = load_model()
30
 
31
  # Ensure the model is loaded before proceeding
32
  if model is None:
33
  st.stop()
34
 
35
+ # Function to normalize landmarks
36
+ def normalize_landmarks(landmarks):
37
+ """Normalize the hand landmarks by centering and scaling.
38
+
39
+ Args:
40
+ landmarks (np.ndarray): Array of hand landmarks.
41
+
42
+ Returns:
43
+ np.ndarray: Normalized landmarks.
44
+ """
45
+ center = np.mean(landmarks, axis=0)
46
+ landmarks_centered = landmarks - center
47
+ std_dev = np.std(landmarks_centered, axis=0)
48
+ landmarks_normalized = landmarks_centered / std_dev
49
+ return np.nan_to_num(landmarks_normalized)
50
+
51
+ # Function to calculate angles between landmarks
52
+ def calculate_angles(landmarks):
53
+ """Calculate angles between hand landmarks.
54
+
55
+ Args:
56
+ landmarks (np.ndarray): Array of normalized hand landmarks.
57
+
58
+ Returns:
59
+ list: List of calculated angles.
60
+ """
61
+ angles = []
62
+ for i in range(20):
63
+ for j in range(i + 1, 21):
64
+ vector = landmarks[j] - landmarks[i]
65
+ angle_x = np.arccos(np.clip(vector[0] / norm(vector), -1.0, 1.0))
66
+ angle_y = np.arccos(np.clip(vector[1] / norm(vector), -1.0, 1.0))
67
+ angles.extend([angle_x, angle_y])
68
+ return angles
69
+
70
+ # Function to process image and predict alphabet
71
+ def process_and_predict(image):
72
+ """Process the input image and predict the ASL sign.
73
+
74
+ Args:
75
+ image (np.ndarray): The input image containing a hand sign.
76
+
77
+ Returns:
78
+ tuple: (probabilities, landmarks) where probabilities are
79
+ the predicted probabilities for each class and landmarks
80
+ are the detected hand landmarks.
81
+ """
82
+ mp_hands = mp.solutions.hands
83
+ with mp_hands.Hands(static_image_mode=True, max_num_hands=1, min_detection_confidence=0.5) as hands:
84
+ image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
85
+ results = hands.process(image_rgb)
86
+
87
+ if results.multi_hand_landmarks:
88
+ landmarks = np.array([[lm.x, lm.y] for lm in results.multi_hand_landmarks[0].landmark])
89
+ landmarks_normalized = normalize_landmarks(landmarks)
90
+ angles = calculate_angles(landmarks_normalized)
91
+
92
+ angle_columns = [f'angle_{i}' for i in range(len(angles))]
93
+ angles_df = pd.DataFrame([angles], columns=angle_columns)
94
+
95
+ probabilities = model.predict_proba(angles_df)[0]
96
+ return probabilities, landmarks
97