Spaces:
Sleeping
Sleeping
File size: 3,026 Bytes
e0e981c 04fcb4d e0e981c 314b8df e0e981c 04fcb4d e0e981c 314b8df e0e981c 314b8df e0e981c 04fcb4d e0e981c 092fbf5 e0e981c 314b8df e16933e 314b8df e16933e 314b8df 092fbf5 314b8df e0e981c e16933e 092fbf5 e0e981c 04fcb4d e0e981c 314b8df e0e981c 314b8df 092fbf5 314b8df 092fbf5 314b8df e0e981c 314b8df e0e981c 314b8df e0e981c 092fbf5 | 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 | import cv2
import mediapipe as mp
import numpy as np
import torch
import torch.nn as nn
import gradio as gr
# ----------------------------
# Labels
# ----------------------------
GESTURE_LABELS = {
0: "A", 1: "B", 2: "L", 3: "U", 4: "V", 5: "W",
6: "Z", 7: "F", 8: "five", 9: "one", 10: "three",
11: "two", 12: "six", 13: "seven", 14: "eight",
15: "nine", 16: "ten", 17: "E", 18: "four",
19: "i", 20: "k", 21: "r", 22: "zero",
23: "m", 24: "s"
}
CONF_THRESHOLD = 0.6
# ----------------------------
# Model
# ----------------------------
class GestureNet(nn.Module):
def __init__(self, input_size=126, num_classes=len(GESTURE_LABELS)):
super().__init__()
self.fc1 = nn.Linear(input_size, 256)
self.fc2 = nn.Linear(256, 128)
self.fc3 = nn.Linear(128, num_classes)
self.relu = nn.ReLU()
self.dropout = nn.Dropout(0.3)
def forward(self, x):
x = self.relu(self.fc1(x))
x = self.dropout(x)
x = self.relu(self.fc2(x))
x = self.dropout(x)
return self.fc3(x)
model = GestureNet()
model.load_state_dict(torch.load("gesture_model1.pth", map_location="cpu"))
model.eval()
# ----------------------------
# MediaPipe
# ----------------------------
mp_hands = mp.solutions.hands
# ----------------------------
# Predict
# ----------------------------
def predict(image):
# Gradio sends RGB, convert to BGR for OpenCV then back to RGB for MediaPipe
image_bgr = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
with mp_hands.Hands(static_image_mode=True, max_num_hands=2) as hands:
results = hands.process(image_rgb)
coords = []
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
hand_coords = np.array([[lm.x, lm.y, lm.z] for lm in hand_landmarks.landmark])
hand_coords -= hand_coords[0]
max_val = np.max(np.linalg.norm(hand_coords, axis=1))
if max_val > 0:
hand_coords /= max_val
coords.extend(hand_coords.flatten())
if len(coords) < 126:
coords.extend([0.0] * (126 - len(coords)))
elif len(coords) > 126:
coords = coords[:126]
if len(coords) == 126:
input_tensor = torch.tensor(coords, dtype=torch.float32).unsqueeze(0)
with torch.no_grad():
outputs = model(input_tensor)
probs = torch.softmax(outputs, dim=1)
pred_class = torch.argmax(probs, dim=1).item()
confidence = probs[0][pred_class].item()
if confidence >= CONF_THRESHOLD:
return f"{GESTURE_LABELS[pred_class]} ({confidence*100:.2f}%)"
return "Unknown"
# ----------------------------
# Gradio UI
# ----------------------------
app = gr.Interface(
fn=predict,
inputs=gr.Image(type="numpy"),
outputs="text",
title="Hand Gesture Recognition",
description="Upload an image of a hand gesture to recognize it."
)
app.launch() |