tommulder commited on
Commit
afecd35
·
1 Parent(s): dd24072

Gesture simplification

Browse files
Dockerfile CHANGED
@@ -29,18 +29,18 @@ WORKDIR $HOME/app
29
  RUN pip install --no-cache-dir --upgrade pip
30
 
31
  # Copy requirements first for better Docker layer caching
32
- COPY --chown=user requirements.txt $HOME/app/
33
 
34
  # Install Python dependencies
35
  RUN pip install --no-cache-dir --user -r requirements.txt
36
 
37
- # Copy the source code
38
- COPY --chown=user src/ $HOME/app/src/
39
- COPY --chown=user models/ $HOME/app/models/
40
 
41
- # Copy the main entry point
42
- COPY --chown=user main.py $HOME/app/
43
- COPY --chown=user README.md $HOME/app/
44
 
45
  # Expose the port that the app runs on (HF Spaces default is 7860)
46
  EXPOSE 7860
 
29
  RUN pip install --no-cache-dir --upgrade pip
30
 
31
  # Copy requirements first for better Docker layer caching
32
+ COPY --chown=user docker/requirements.txt $HOME/app/
33
 
34
  # Install Python dependencies
35
  RUN pip install --no-cache-dir --user -r requirements.txt
36
 
37
+ # Copy the source code from parent directory
38
+ COPY --chown=user ../src/ $HOME/app/src/
39
+ COPY --chown=user ../models/ $HOME/app/models/
40
 
41
+ # Copy the main entry point from parent directory
42
+ COPY --chown=user ../main.py $HOME/app/
43
+ COPY --chown=user ../README.md $HOME/app/
44
 
45
  # Expose the port that the app runs on (HF Spaces default is 7860)
46
  EXPOSE 7860
src/gesturedetection/__pycache__/api.cpython-312.pyc CHANGED
Binary files a/src/gesturedetection/__pycache__/api.cpython-312.pyc and b/src/gesturedetection/__pycache__/api.cpython-312.pyc differ
 
src/gesturedetection/__pycache__/models.cpython-312.pyc CHANGED
Binary files a/src/gesturedetection/__pycache__/models.cpython-312.pyc and b/src/gesturedetection/__pycache__/models.cpython-312.pyc differ
 
src/gesturedetection/api.py CHANGED
@@ -8,7 +8,7 @@ from fastapi import FastAPI, UploadFile, File, HTTPException, Form
8
  from fastapi.responses import ORJSONResponse
9
  from fastapi.encoders import jsonable_encoder
10
 
11
- from .models import Gesture, GestureResponse, GESTURE_MAPPING, FULL_GESTURE_MAPPING
12
  from .config import get_logfire_token, is_monitoring_enabled
13
 
14
  # Import the gesture detection components
@@ -178,7 +178,7 @@ def process_video_for_gestures(video_path: str, detector_path: str = "models/han
178
  # Adjust minimum duration based on frame skip
179
  min_duration = max(5, frame_skip * 2) # At least 2 processed frames
180
  if current_gesture is not None and current_duration >= min_duration:
181
- gesture_name = FULL_GESTURE_MAPPING.get(current_gesture, f"unknown_{current_gesture}")
182
  avg_confidence = current_confidence / current_duration if current_duration > 0 else 0.0
183
  # Scale duration back to original frame count
184
  scaled_duration = current_duration * frame_skip
@@ -208,7 +208,7 @@ def process_video_for_gestures(video_path: str, detector_path: str = "models/han
208
  # Don't forget the last gesture
209
  min_duration = max(5, frame_skip * 2) # At least 2 processed frames
210
  if current_gesture is not None and current_duration >= min_duration:
211
- gesture_name = FULL_GESTURE_MAPPING.get(current_gesture, f"unknown_{current_gesture}")
212
  avg_confidence = current_confidence / current_duration if current_duration > 0 else 0.0
213
  # Scale duration back to original frame count
214
  scaled_duration = current_duration * frame_skip
 
8
  from fastapi.responses import ORJSONResponse
9
  from fastapi.encoders import jsonable_encoder
10
 
11
+ from .models import Gesture, GestureResponse, GESTURE_MAPPING, FULL_GESTURE_MAPPING, PRODUCTION_GESTURE_MAPPING
12
  from .config import get_logfire_token, is_monitoring_enabled
13
 
14
  # Import the gesture detection components
 
178
  # Adjust minimum duration based on frame skip
179
  min_duration = max(5, frame_skip * 2) # At least 2 processed frames
180
  if current_gesture is not None and current_duration >= min_duration:
181
+ gesture_name = PRODUCTION_GESTURE_MAPPING.get(current_gesture, f"unknown_{current_gesture}")
182
  avg_confidence = current_confidence / current_duration if current_duration > 0 else 0.0
183
  # Scale duration back to original frame count
184
  scaled_duration = current_duration * frame_skip
 
208
  # Don't forget the last gesture
209
  min_duration = max(5, frame_skip * 2) # At least 2 processed frames
210
  if current_gesture is not None and current_duration >= min_duration:
211
+ gesture_name = PRODUCTION_GESTURE_MAPPING.get(current_gesture, f"unknown_{current_gesture}")
212
  avg_confidence = current_confidence / current_duration if current_duration > 0 else 0.0
213
  # Scale duration back to original frame count
214
  scaled_duration = current_duration * frame_skip
src/gesturedetection/models.py CHANGED
@@ -39,7 +39,43 @@ GESTURE_MAPPING = {
39
  35: "stop", # stop gesture
40
  }
41
 
42
- # Additional gesture mappings for completeness
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  FULL_GESTURE_MAPPING = {
44
  0: "hand_down",
45
  1: "hand_right",
 
39
  35: "stop", # stop gesture
40
  }
41
 
42
+ # Production gesture mapping with clean, consistent names
43
+ # Hand-agnostic counting (left/right variations map to same gesture)
44
+ PRODUCTION_GESTURE_MAPPING = {
45
+ # Counting gestures (1-5) - hand agnostic
46
+ 30: "one", # 1 finger (any direction)
47
+ 42: "one", # 1 finger left (maps to "one")
48
+ 43: "one", # 1 finger right (maps to "one")
49
+ 44: "one", # 1 finger down (maps to "one")
50
+
51
+ 32: "two", # 2 fingers (peace sign)
52
+ 39: "two", # 2 fingers up (maps to "two")
53
+ 14: "two", # 2 fingers left (maps to "two")
54
+ 15: "two", # 2 fingers right (maps to "two")
55
+ 16: "two", # 2 fingers down (maps to "two")
56
+
57
+ 37: "three", # 3 fingers (any direction)
58
+ 21: "three", # 3 fingers variant (maps to "three")
59
+ 38: "three", # 3 fingers variant 2 (maps to "three")
60
+
61
+ 26: "four", # 4 fingers
62
+
63
+ 31: "five", # 5 fingers (open palm)
64
+
65
+ # Extra gestures for production
66
+ 27: "thumbs_up", # thumbs up gesture
67
+ 23: "middle_finger", # middle finger
68
+ 33: "peace_inverted", # peace sign inverted
69
+
70
+ # Additional useful gestures
71
+ 29: "ok", # OK sign
72
+ 20: "call", # call me gesture
73
+ 25: "fist", # closed fist
74
+ 19: "point", # pointing
75
+ 35: "stop", # stop gesture
76
+ }
77
+
78
+ # Additional gesture mappings for completeness (all raw model outputs)
79
  FULL_GESTURE_MAPPING = {
80
  0: "hand_down",
81
  1: "hand_right",
src/validate/__pycache__/__init__.cpython-312.pyc CHANGED
Binary files a/src/validate/__pycache__/__init__.cpython-312.pyc and b/src/validate/__pycache__/__init__.cpython-312.pyc differ
 
src/validate/__pycache__/gesture_validator.cpython-312.pyc CHANGED
Binary files a/src/validate/__pycache__/gesture_validator.cpython-312.pyc and b/src/validate/__pycache__/gesture_validator.cpython-312.pyc differ
 
src/validate/__pycache__/models.cpython-312.pyc CHANGED
Binary files a/src/validate/__pycache__/models.cpython-312.pyc and b/src/validate/__pycache__/models.cpython-312.pyc differ
 
src/validate/gesture_validator.py CHANGED
@@ -60,11 +60,11 @@ class GestureValidator:
60
  # Import here to avoid circular imports and handle missing dependencies gracefully
61
  try:
62
  from ..gesturedetection.main_controller import MainController
63
- from ..gesturedetection.models import FULL_GESTURE_MAPPING
64
  self._main_controller_class = MainController
65
- self._gesture_mapping = FULL_GESTURE_MAPPING
66
  self._initialized = True
67
- logger.info("GestureValidator initialized successfully")
68
  except ImportError as e:
69
  logger.warning(f"Could not import gesture detection components: {e}")
70
  self._initialized = False
@@ -458,7 +458,11 @@ class GestureValidator:
458
 
459
  def _normalize_gesture_name(self, gesture_name: str) -> str:
460
  """
461
- Normalize gesture names to standard format.
 
 
 
 
462
 
463
  Parameters
464
  ----------
@@ -468,25 +472,26 @@ class GestureValidator:
468
  Returns
469
  -------
470
  str
471
- Normalized gesture name
472
  """
473
  # Convert to lowercase and remove common variations
474
  normalized = gesture_name.lower().strip()
475
 
476
- # Handle common variations
477
  variations = {
478
- "thumbs_up": ["thumbsup", "thumb_up", "like"],
479
- "peace": ["peace_sign", "victory", "two_fingers"],
 
 
 
 
 
480
  "ok": ["okay", "ok_sign"],
481
  "call": ["call_me", "phone"],
482
- "palm": ["open_palm", "five_fingers"],
483
  "fist": ["closed_fist"],
484
  "point": ["pointing"],
485
  "stop": ["stop_sign"],
486
- "one": ["one_finger"],
487
- "two_up": ["two_fingers_up"],
488
- "three": ["three_fingers"],
489
- "four": ["four_fingers"]
490
  }
491
 
492
  for standard_name, variant_list in variations.items():
 
60
  # Import here to avoid circular imports and handle missing dependencies gracefully
61
  try:
62
  from ..gesturedetection.main_controller import MainController
63
+ from ..gesturedetection.models import PRODUCTION_GESTURE_MAPPING
64
  self._main_controller_class = MainController
65
+ self._gesture_mapping = PRODUCTION_GESTURE_MAPPING
66
  self._initialized = True
67
+ logger.info("GestureValidator initialized successfully with PRODUCTION_GESTURE_MAPPING")
68
  except ImportError as e:
69
  logger.warning(f"Could not import gesture detection components: {e}")
70
  self._initialized = False
 
458
 
459
  def _normalize_gesture_name(self, gesture_name: str) -> str:
460
  """
461
+ Normalize gesture names to production-standard format.
462
+
463
+ Handles legacy naming and variations to ensure consistent gesture names
464
+ across different parts of the system. Maps old names like "like" to
465
+ "thumbs_up", and handles hand-agnostic counting variations.
466
 
467
  Parameters
468
  ----------
 
472
  Returns
473
  -------
474
  str
475
+ Normalized gesture name matching PRODUCTION_GESTURE_MAPPING
476
  """
477
  # Convert to lowercase and remove common variations
478
  normalized = gesture_name.lower().strip()
479
 
480
+ # Handle common variations and legacy names
481
  variations = {
482
+ "thumbs_up": ["thumbsup", "thumb_up", "like"], # "like" is legacy name
483
+ "one": ["one_finger", "one_left", "one_right", "one_down"], # Hand-agnostic
484
+ "two": ["peace_sign", "victory", "two_fingers", "two_up", "two_left", "two_right", "two_down"], # Hand-agnostic
485
+ "three": ["three_fingers", "three2", "three3"], # Hand-agnostic
486
+ "four": ["four_fingers"],
487
+ "five": ["palm", "open_palm", "five_fingers"], # "palm" is alias for "five"
488
+ "peace_inverted": ["peace_inverted_sign"],
489
  "ok": ["okay", "ok_sign"],
490
  "call": ["call_me", "phone"],
 
491
  "fist": ["closed_fist"],
492
  "point": ["pointing"],
493
  "stop": ["stop_sign"],
494
+ "middle_finger": ["middle"],
 
 
 
495
  }
496
 
497
  for standard_name, variant_list in variations.items():