Mathematicaljuice commited on
Commit
e16933e
·
verified ·
1 Parent(s): 6011de6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -39
app.py CHANGED
@@ -1,7 +1,5 @@
1
  import cv2
2
  import mediapipe as mp
3
- from mediapipe.tasks.python import vision
4
- from mediapipe.tasks.python import BaseOptions
5
  import numpy as np
6
  import torch
7
  import torch.nn as nn
@@ -27,73 +25,101 @@ CONF_THRESHOLD = 0.6
27
  class GestureNet(nn.Module):
28
  def __init__(self, input_size=126, num_classes=len(GESTURE_LABELS)):
29
  super().__init__()
 
30
  self.fc1 = nn.Linear(input_size, 256)
31
  self.fc2 = nn.Linear(256, 128)
32
  self.fc3 = nn.Linear(128, num_classes)
 
33
  self.relu = nn.ReLU()
34
  self.dropout = nn.Dropout(0.3)
35
 
36
  def forward(self, x):
37
  x = self.relu(self.fc1(x))
38
  x = self.dropout(x)
 
39
  x = self.relu(self.fc2(x))
40
  x = self.dropout(x)
 
41
  return self.fc3(x)
42
 
 
 
 
43
  model = GestureNet()
44
- model.load_state_dict(torch.load("gesture_model1.pth", map_location="cpu"))
 
 
 
 
45
  model.eval()
46
 
47
  # ----------------------------
48
- # MediaPipe HandLandmarker
49
  # ----------------------------
50
- # Initialize the HandLandmarker once for efficiency
51
- model_path = "hand_landmarker.task" # You may need to download this file
52
- # If you don't have the model file, uncomment the next line to download automatically:
53
- # import urllib.request; urllib.request.urlretrieve("https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task", "hand_landmarker.task")
54
-
55
- base_options = BaseOptions(model_asset_path=model_path)
56
- options = vision.HandLandmarkerOptions(base_options=base_options, num_hands=2)
57
- landmarker = vision.HandLandmarker.create_from_options(options)
58
-
59
- def extract_hand_features(image_rgb):
60
- """Extract normalized 63 landmarks (x,y,z) from up to 2 hands, returns flattened list of length 126."""
61
- mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=image_rgb)
62
- detection_result = landmarker.detect(mp_image)
 
 
 
 
 
 
 
63
  coords = []
64
 
65
- if detection_result.hand_landmarks:
66
- for hand_landmarks in detection_result.hand_landmarks:
67
- # Convert to numpy array of shape (21, 3)
68
- hand_coords = np.array([[lm.x, lm.y, lm.z] for lm in hand_landmarks])
69
- # Normalize: subtract wrist (index 0) and scale by max distance
 
 
 
 
 
70
  hand_coords -= hand_coords[0]
 
71
  max_val = np.max(np.linalg.norm(hand_coords, axis=1))
 
72
  if max_val > 0:
73
  hand_coords /= max_val
 
74
  coords.extend(hand_coords.flatten())
75
 
76
- # Pad or truncate to fixed length 126 (21*3*2)
77
  if len(coords) < 126:
78
  coords.extend([0.0] * (126 - len(coords)))
 
79
  elif len(coords) > 126:
80
  coords = coords[:126]
81
- return coords
82
 
83
- def predict(image):
84
- # Convert BGR (Gradio default) to RGB
85
- image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
86
- features = extract_hand_features(image_rgb)
87
-
88
- if len(features) == 126:
89
- input_tensor = torch.tensor(features, dtype=torch.float32).unsqueeze(0)
90
- with torch.no_grad():
91
- outputs = model(input_tensor)
92
- probs = torch.softmax(outputs, dim=1).numpy()[0]
93
- pred_class = np.argmax(probs)
94
- confidence = probs[pred_class]
95
- if confidence >= CONF_THRESHOLD:
96
- return f"{GESTURE_LABELS[pred_class]} ({confidence*100:.2f}%)"
 
 
97
  return "Unknown"
98
 
99
  # ----------------------------
@@ -107,4 +133,7 @@ app = gr.Interface(
107
  description="Upload an image of a hand gesture"
108
  )
109
 
110
- app.launch()
 
 
 
 
1
  import cv2
2
  import mediapipe as mp
 
 
3
  import numpy as np
4
  import torch
5
  import torch.nn as nn
 
25
  class GestureNet(nn.Module):
26
  def __init__(self, input_size=126, num_classes=len(GESTURE_LABELS)):
27
  super().__init__()
28
+
29
  self.fc1 = nn.Linear(input_size, 256)
30
  self.fc2 = nn.Linear(256, 128)
31
  self.fc3 = nn.Linear(128, num_classes)
32
+
33
  self.relu = nn.ReLU()
34
  self.dropout = nn.Dropout(0.3)
35
 
36
  def forward(self, x):
37
  x = self.relu(self.fc1(x))
38
  x = self.dropout(x)
39
+
40
  x = self.relu(self.fc2(x))
41
  x = self.dropout(x)
42
+
43
  return self.fc3(x)
44
 
45
+ # ----------------------------
46
+ # Load Model
47
+ # ----------------------------
48
  model = GestureNet()
49
+
50
+ model.load_state_dict(
51
+ torch.load("gesture_model1.pth", map_location=torch.device("cpu"))
52
+ )
53
+
54
  model.eval()
55
 
56
  # ----------------------------
57
+ # MediaPipe
58
  # ----------------------------
59
+ mp_hands = mp.solutions.hands
60
+
61
+ hands = mp_hands.Hands(
62
+ static_image_mode=True,
63
+ max_num_hands=2,
64
+ min_detection_confidence=0.5
65
+ )
66
+
67
+ # ----------------------------
68
+ # Prediction Function
69
+ # ----------------------------
70
+ def predict(image):
71
+
72
+ if image is None:
73
+ return "No image uploaded"
74
+
75
+ image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
76
+
77
+ results = hands.process(image_rgb)
78
+
79
  coords = []
80
 
81
+ if results.multi_hand_landmarks:
82
+
83
+ for hand_landmarks in results.multi_hand_landmarks:
84
+
85
+ hand_coords = np.array([
86
+ [lm.x, lm.y, lm.z]
87
+ for lm in hand_landmarks.landmark
88
+ ])
89
+
90
+ # Normalize
91
  hand_coords -= hand_coords[0]
92
+
93
  max_val = np.max(np.linalg.norm(hand_coords, axis=1))
94
+
95
  if max_val > 0:
96
  hand_coords /= max_val
97
+
98
  coords.extend(hand_coords.flatten())
99
 
100
+ # Padding
101
  if len(coords) < 126:
102
  coords.extend([0.0] * (126 - len(coords)))
103
+
104
  elif len(coords) > 126:
105
  coords = coords[:126]
 
106
 
107
+ input_tensor = torch.tensor(
108
+ coords,
109
+ dtype=torch.float32
110
+ ).unsqueeze(0)
111
+
112
+ with torch.no_grad():
113
+ outputs = model(input_tensor)
114
+
115
+ probs = torch.softmax(outputs, dim=1).cpu().numpy()[0]
116
+
117
+ pred_class = np.argmax(probs)
118
+ confidence = probs[pred_class]
119
+
120
+ if confidence >= CONF_THRESHOLD:
121
+ return f"{GESTURE_LABELS[pred_class]} ({confidence*100:.2f}%)"
122
+
123
  return "Unknown"
124
 
125
  # ----------------------------
 
133
  description="Upload an image of a hand gesture"
134
  )
135
 
136
+ # ----------------------------
137
+ # Launch
138
+ # ----------------------------
139
+ app.launch(server_name="0.0.0.0", server_port=7860)