File size: 4,279 Bytes
c7f34f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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
111
112
113
114
115
116
117
import streamlit as st
import cv2
import numpy as np
import mediapipe as mp
import pickle
import os

# Define the models directory
models_dir = 'models'

# Load models
def load_model(file_path):
    try:
        with open(file_path, 'rb') as file:
            return pickle.load(file)
    except FileNotFoundError:
        st.error(f"Error: Model file not found at {file_path}")
    except Exception as e:
        st.error(f"Error loading model from {file_path}: {e}")
    return None

models = {
    'Random Forest': load_model(os.path.join(models_dir, 'random_forest_model.pkl')),
    'SVM': load_model(os.path.join(models_dir, 'svm_model.pkl')),
    'Hard Voting': load_model(os.path.join(models_dir, 'hard_voting_classifier.pkl')),
    'Soft Voting': load_model(os.path.join(models_dir, 'soft_voting_classifier.pkl'))
}

# Load label encoder
label_encoder = load_model(os.path.join(models_dir, 'label_encoder.pkl'))
if label_encoder is None:
    st.error("Failed to load label encoder. Exiting.")
    st.stop()

# Initialize MediaPipe Hands
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(static_image_mode=True, max_num_hands=1, min_detection_confidence=0.5)

def process_landmarks(hand_landmarks):
    x_ = [landmark.x for landmark in hand_landmarks.landmark]
    y_ = [landmark.y for landmark in hand_landmarks.landmark]
    min_x, min_y = min(x_), min(y_)
    return [coord - min_val for landmark in hand_landmarks.landmark for coord, min_val in zip((landmark.x, landmark.y), (min_x, min_y))]

def get_model_predictions(data_aux, model):
    if hasattr(model, 'predict_proba'):
        probabilities = model.predict_proba([data_aux])[0]
    elif hasattr(model, 'decision_function'):
        scores = model.decision_function([data_aux])[0]
        probabilities = (scores - scores.min()) / (scores.max() - scores.min())
    else:
        class_pred = model.predict([data_aux])[0]
        probabilities = np.zeros(len(label_encoder.classes_))
        probabilities[class_pred] = 1

    top_index = np.argmax(probabilities)
    return label_encoder.inverse_transform([top_index])[0], probabilities[top_index]

def predict_alphabet(image):
    image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    results = hands.process(image_rgb)

    if not results.multi_hand_landmarks:
        return None, None

    data_aux = process_landmarks(results.multi_hand_landmarks[0])
    predictions = {}

    for model_name, model in models.items():
        if model is None:
            continue
        prediction, probability = get_model_predictions(data_aux, model)
        predictions[model_name] = (prediction, probability)

    return predictions, results.multi_hand_landmarks[0]

def draw_hand_landmarks(image, hand_landmarks):
    for landmark in hand_landmarks.landmark:
        h, w, _ = image.shape
        cx, cy = int(landmark.x * w), int(landmark.y * h)
        cv2.circle(image, (cx, cy), 5, (0, 255, 0), -1)
    return image

# Streamlit App
st.title("ASL Hand Shape Recognition App")

uploaded_file = st.file_uploader("Choose a hand image...", type=["jpg", "jpeg", "png"])

if uploaded_file is not None:
    image = cv2.imdecode(np.frombuffer(uploaded_file.read(), np.uint8), 1)
    st.image(image, channels="BGR", caption="Uploaded Hand Image")

    predictions, hand_landmarks = predict_alphabet(image)

    if predictions and hand_landmarks:
        st.subheader("Predictions:")
        for model_name, (prediction, probability) in predictions.items():
            st.write(f"{model_name}: {prediction} (Probability: {probability:.2f})")

        st.subheader("Hand Landmarks:")
        landmark_image = draw_hand_landmarks(image.copy(), hand_landmarks)
        st.image(landmark_image, channels="BGR", caption="Hand Landmarks")
    else:
        st.write("No hand detected in the image.")

# User input to draw hand sign (placeholder)
user_input = st.text_input("Enter alphabet to draw hand sign:")
if user_input:
    if len(user_input) == 1 and user_input.isalpha():
        st.write(f"Drawing hand sign for alphabet: {user_input.upper()}")
        # Placeholder for drawing hand sign
        st.write("(Hand sign drawing functionality not implemented)")
    else:
        st.error("Please enter a single alphabet.")

# Release MediaPipe resources
hands.close()