Download src/mp_tracker.py from ayzeksalimli/hand-tracking-drawing: direct link, hf CLI and curl.
- Browser
- Download file 2.59 kB
-
https://huggingface.co/ayzeksalimli/hand-tracking-drawing/resolve/main/src/mp_tracker.py
- Command line
-
hf download hf://ayzeksalimli/hand-tracking-drawing/src/mp_tracker.py
-
curl -L -o mp_tracker.py https://huggingface.co/ayzeksalimli/hand-tracking-drawing/resolve/main/src/mp_tracker.py
2.59 kB
| from __future__ import annotations | |
| import os | |
| import time | |
| from pathlib import Path | |
| os.environ.setdefault("GLOG_minloglevel", "3") | |
| import numpy as np | |
| from hand import Hand | |
| class MediaPipeTracker: | |
| """MediaPipe hand landmarker.""" | |
| def __init__( | |
| self, | |
| model_path: str | Path, | |
| conf: float = 0.4, | |
| max_hands: int = 2, | |
| video_mode: bool = True, | |
| **_ignored, | |
| ) -> None: | |
| import mediapipe as mp | |
| from mediapipe.tasks.python import BaseOptions, vision | |
| model_path = Path(model_path) | |
| if not model_path.exists(): | |
| raise FileNotFoundError(f"Model not found: {model_path}") | |
| self._mp = mp | |
| self.device = "cpu" | |
| self.max_hands = max_hands | |
| self.video_mode = video_mode | |
| mode = vision.RunningMode.VIDEO if video_mode else vision.RunningMode.IMAGE | |
| options = vision.HandLandmarkerOptions( | |
| base_options=BaseOptions(model_asset_path=str(model_path)), | |
| running_mode=mode, | |
| num_hands=max_hands, | |
| min_hand_detection_confidence=conf, | |
| min_hand_presence_confidence=conf, | |
| min_tracking_confidence=0.5, | |
| ) | |
| self.detector = vision.HandLandmarker.create_from_options(options) | |
| self._t0 = time.perf_counter() | |
| self._last_ts = -1 | |
| def __call__(self, frame: np.ndarray) -> list[Hand]: | |
| """Detect hands in frame.""" | |
| h, w = frame.shape[:2] | |
| rgb = frame[:, :, ::-1].copy() | |
| image = self._mp.Image(image_format=self._mp.ImageFormat.SRGB, data=rgb) | |
| if self.video_mode: | |
| ts = max(int((time.perf_counter() - self._t0) * 1000), self._last_ts + 1) | |
| self._last_ts = ts | |
| result = self.detector.detect_for_video(image, ts) | |
| else: | |
| result = self.detector.detect(image) | |
| hands: list[Hand] = [] | |
| for i, lms in enumerate(result.hand_landmarks): | |
| kp = np.array([[lm.x * w, lm.y * h] for lm in lms], dtype=np.float64) | |
| conf = 1.0 | |
| if result.handedness and i < len(result.handedness): | |
| conf = float(result.handedness[i][0].score) | |
| box = np.array([kp[:, 0].min(), kp[:, 1].min(), | |
| kp[:, 0].max(), kp[:, 1].max()], dtype=np.float64) | |
| hands.append(Hand(keypoints=kp, scores=np.ones(21), box=box, conf=conf)) | |
| hands.sort(key=lambda x: x.conf, reverse=True) | |
| return hands[: self.max_hands] | |
| def close(self) -> None: | |
| """Release detector.""" | |
| self.detector.close() | |