Niharmahesh commited on
Commit
458a95e
1 Parent(s): d1c5054

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +129 -11
app.py CHANGED
@@ -18,7 +18,11 @@ working_alphabets = ''.join(set(all_alphabets) - set(excluded_alphabets))
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:
@@ -34,13 +38,13 @@ if model is None:
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
@@ -53,10 +57,10 @@ 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):
@@ -69,15 +73,13 @@ def calculate_angles(landmarks):
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:
@@ -95,3 +97,119 @@ def process_and_predict(image):
95
  probabilities = model.predict_proba(angles_df)[0]
96
  return probabilities, landmarks
97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  # Function to load the Random Forest model
19
  @st.cache_resource
20
  def load_model():
21
+ """Load the pre-trained Random Forest model.
22
+
23
+ Returns:
24
+ model: The loaded Random Forest model.
25
+ """
26
  try:
27
  return joblib.load('best_random_forest_model.pkl')
28
  except Exception as e:
 
38
 
39
  # Function to normalize landmarks
40
  def normalize_landmarks(landmarks):
41
+ """Normalize the landmark coordinates.
42
 
43
  Args:
44
+ landmarks (np.ndarray): The array of landmark coordinates.
45
 
46
  Returns:
47
+ np.ndarray: Normalized landmark coordinates.
48
  """
49
  center = np.mean(landmarks, axis=0)
50
  landmarks_centered = landmarks - center
 
57
  """Calculate angles between hand landmarks.
58
 
59
  Args:
60
+ landmarks (np.ndarray): The array of normalized landmark coordinates.
61
 
62
  Returns:
63
+ list: List of angles between landmarks.
64
  """
65
  angles = []
66
  for i in range(20):
 
73
 
74
  # Function to process image and predict alphabet
75
  def process_and_predict(image):
76
+ """Process the uploaded image to predict the ASL sign.
77
 
78
  Args:
79
+ image (np.ndarray): The uploaded image in BGR format.
80
 
81
  Returns:
82
+ tuple: (probabilities of each class, detected landmarks)
 
 
83
  """
84
  mp_hands = mp.solutions.hands
85
  with mp_hands.Hands(static_image_mode=True, max_num_hands=1, min_detection_confidence=0.5) as hands:
 
97
  probabilities = model.predict_proba(angles_df)[0]
98
  return probabilities, landmarks
99
 
100
+ return None, None
101
+
102
+ # Function to plot hand landmarks
103
+ def plot_hand_landmarks(landmarks, title):
104
+ """Plot the detected hand landmarks.
105
+
106
+ Args:
107
+ landmarks (np.ndarray): The array of landmark coordinates.
108
+ title (str): The title for the plot.
109
+
110
+ Returns:
111
+ Figure: The matplotlib figure object with plotted landmarks.
112
+ """
113
+ fig, ax = plt.subplots(figsize=(5, 5))
114
+ ax.scatter(landmarks[:, 0], landmarks[:, 1], c='blue', s=20)
115
+ mp_hands = mp.solutions.hands
116
+ for connection in mp_hands.HAND_CONNECTIONS:
117
+ start_idx = connection[0]
118
+ end_idx = connection[1]
119
+ ax.plot([landmarks[start_idx, 0], landmarks[end_idx, 0]],
120
+ [landmarks[start_idx, 1], landmarks[end_idx, 1]], 'r-', linewidth=1)
121
+ ax.invert_yaxis()
122
+ ax.set_title(title, fontsize=12)
123
+ ax.axis('off')
124
+ return fig
125
+
126
+ # README content
127
+ readme_content = f"""
128
+ ## How it works
129
+
130
+ This ASL Recognition App uses image processing and machine learning to recognize American Sign Language (ASL) hand signs.
131
+
132
+ 1. **Image Upload**: Users can upload an image of an ASL hand sign.
133
+ 2. **Hand Detection**: The app uses MediaPipe to detect hand landmarks in the image.
134
+ 3. **Feature Extraction**: Angles between hand landmarks are calculated and normalized.
135
+ 4. **Prediction**: A Random Forest model predicts the ASL sign based on the extracted features.
136
+ 5. **Visualization**: The app displays the detected hand landmarks and top predictions.
137
+
138
+ ### Supported Alphabets
139
+
140
+ The app currently works for the following ASL alphabets:
141
+ {', '.join(working_alphabets)}
142
+
143
+ The app does not support or may not work correctly for:
144
+ {', '.join(excluded_alphabets)}
145
+
146
+ Note: The model's performance may vary and is subject to improvement.
147
+
148
+ The "View Hand Landmarks" tab allows users to see hand landmarks for pre-loaded ASL signs.
149
+ """
150
+
151
+ # Streamlit app
152
+ st.title("ASL Recognition App")
153
+
154
+ # Display README content
155
+ st.sidebar.markdown(readme_content)
156
+
157
+ # Create tabs for different functionalities
158
+ tab1, tab2 = st.tabs(["Predict ASL Sign", "View Hand Landmarks"])
159
+
160
+ with tab1:
161
+ st.header("Predict ASL Sign")
162
+ uploaded_file = st.file_uploader("Upload an image of an ASL sign", type=["jpg", "jpeg", "png"])
163
+
164
+ if uploaded_file is not None:
165
+ try:
166
+ image = cv2.imdecode(np.frombuffer(uploaded_file.read(), np.uint8), 1)
167
+ if image is not None:
168
+ col1, col2 = st.columns(2)
169
+ with col1:
170
+ st.image(image, caption="Uploaded Image", use_column_width=True)
171
+
172
+ probabilities, landmarks = process_and_predict(image)
173
+
174
+ if probabilities is not None and landmarks is not None:
175
+ with col2:
176
+ st.subheader("Top 5 Predictions:")
177
+ top_indices = np.argsort(probabilities)[::-1][:5]
178
+ for i in top_indices:
179
+ st.write(f"{model.classes_[i]}: {probabilities[i]:.2f}")
180
+
181
+ fig = plot_hand_landmarks(landmarks, "Detected Hand Landmarks")
182
+ st.pyplot(fig)
183
+ else:
184
+ st.write("No hand detected in the image.")
185
+ else:
186
+ st.error("Failed to load the image. The file might be corrupted.")
187
+ except Exception as e:
188
+ st.error(f"An error occurred while processing the image: {str(e)}")
189
+
190
+ with tab2:
191
+ st.header("View Hand Landmarks")
192
+
193
+ selected_alphabets = st.multiselect("Select alphabets to view landmarks:", list(working_alphabets))
194
+
195
+ if selected_alphabets:
196
+ cols = st.columns(4) # 4 columns for smaller images
197
+ for idx, alphabet in enumerate(selected_alphabets):
198
+ with cols[idx % 4]:
199
+ image_path = os.path.join('asl test set', f'{alphabet.lower()}.jpeg')
200
+ if os.path.exists(image_path):
201
+ try:
202
+ image = cv2.imread(image_path)
203
+ if image is not None:
204
+ probabilities, landmarks = process_and_predict(image)
205
+ if landmarks is not None:
206
+ fig = plot_hand_landmarks(landmarks, f"Hand Landmarks for {alphabet}")
207
+ st.pyplot(fig)
208
+ else:
209
+ st.error(f"No hand detected for {alphabet}")
210
+ else:
211
+ st.error(f"Failed to load image for {alphabet}")
212
+ except Exception as e:
213
+ st.error(f"Error processing image for {alphabet}")
214
+ else:
215
+ st.error(f"Image not found for {alphabet}")