Niharmahesh commited on
Commit
5252e41
·
verified ·
1 Parent(s): 313ea3a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +99 -102
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 pickle
6
-
7
- # Load models directly
8
- with open('random_forest_model.pkl', 'rb') as file:
9
- random_forest_model = pickle.load(file)
10
- with open('svm_model.pkl', 'rb') as file:
11
- svm_model = pickle.load(file)
12
- with open('hard_voting_classifier.pkl', 'rb') as file:
13
- hard_voting_model = pickle.load(file)
14
- with open('soft_voting_classifier.pkl', 'rb') as file:
15
- soft_voting_model = pickle.load(file)
16
- label_classes = np.load('label_classes.npy', allow_pickle=True)
17
-
18
-
19
- models = {
20
- 'Random Forest': random_forest_model,
21
- 'SVM': svm_model,
22
- 'Hard Voting': hard_voting_model,
23
- 'Soft Voting': soft_voting_model
24
- }
25
 
26
  # Initialize MediaPipe Hands
27
- mp_hands = mp.solutions.hands
28
- hands = mp_hands.Hands(static_image_mode=True, max_num_hands=1, min_detection_confidence=0.5)
29
-
30
- def process_landmarks(hand_landmarks):
31
- x_ = [landmark.x for landmark in hand_landmarks.landmark]
32
- y_ = [landmark.y for landmark in hand_landmarks.landmark]
33
- min_x, min_y = min(x_), min(y_)
34
- return [coord - min_val for landmark in hand_landmarks.landmark for coord, min_val in zip((landmark.x, landmark.y), (min_x, min_y))]
35
-
36
- def get_model_predictions(data_aux, model):
37
- if hasattr(model, 'predict_proba'):
38
- probabilities = model.predict_proba([data_aux])[0]
39
- elif hasattr(model, 'decision_function'):
40
- scores = model.decision_function([data_aux])[0]
41
- probabilities = (scores - scores.min()) / (scores.max() - scores.min())
42
- else:
43
- class_pred = model.predict([data_aux])[0]
44
- probabilities = np.zeros(len(label_classes))
45
- probabilities[class_pred] = 1
46
-
47
- # Add this check
48
- if not hasattr(model, 'monotonic_cst'):
49
- model.monotonic_cst = None
50
-
51
- top_index = np.argmax(probabilities)
52
- return label_classes[top_index], probabilities[top_index]
53
-
54
- def predict_alphabet(image):
55
- image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
56
- results = hands.process(image_rgb)
57
-
58
- if not results.multi_hand_landmarks:
59
- return None, None
60
-
61
- data_aux = process_landmarks(results.multi_hand_landmarks[0])
62
- predictions = {}
63
-
64
- for model_name, model in models.items():
65
- prediction, probability = get_model_predictions(data_aux, model)
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
- image = cv2.imdecode(np.frombuffer(uploaded_file.read(), np.uint8), 1)
84
- st.image(image, channels="BGR", caption="Uploaded Hand Image")
85
-
86
- predictions, hand_landmarks = predict_alphabet(image)
87
-
88
- if predictions and hand_landmarks:
89
- st.subheader("Predictions:")
90
- for model_name, (prediction, probability) in predictions.items():
91
- st.write(f"{model_name}: {prediction} (Probability: {probability:.2f})")
92
-
93
- st.subheader("Hand Landmarks:")
94
- landmark_image = draw_hand_landmarks(image.copy(), hand_landmarks)
95
- st.image(landmark_image, channels="BGR", caption="Hand Landmarks")
96
- else:
97
- st.write("No hand detected in the image.")
98
-
99
- # User input to draw hand sign (placeholder)
100
- user_input = st.text_input("Enter alphabet to draw hand sign:")
101
- if user_input:
102
- if len(user_input) == 1 and user_input.isalpha():
103
- st.write(f"Drawing hand sign for alphabet: {user_input.upper()}")
104
- # Placeholder for drawing hand sign
105
- st.write("(Hand sign drawing functionality not implemented)")
106
- else:
107
- st.error("Please enter a single alphabet.")
108
-
109
- # Release MediaPipe resources
110
- hands.close()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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}")