File size: 1,381 Bytes
9f85448 | 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 | from __future__ import annotations
from dataclasses import dataclass
import numpy as np
WRIST = 0
THUMB_CMC, THUMB_MCP, THUMB_IP, THUMB_TIP = 1, 2, 3, 4
INDEX_MCP, INDEX_PIP, INDEX_DIP, INDEX_TIP = 5, 6, 7, 8
MIDDLE_MCP, MIDDLE_PIP, MIDDLE_DIP, MIDDLE_TIP = 9, 10, 11, 12
RING_MCP, RING_PIP, RING_DIP, RING_TIP = 13, 14, 15, 16
PINKY_MCP, PINKY_PIP, PINKY_DIP, PINKY_TIP = 17, 18, 19, 20
HAND_CONNECTIONS: tuple[tuple[int, int], ...] = (
(0, 1), (1, 2), (2, 3), (3, 4),
(0, 5), (5, 6), (6, 7), (7, 8),
(5, 9), (9, 10), (10, 11), (11, 12),
(9, 13), (13, 14), (14, 15), (15, 16),
(13, 17), (17, 18), (18, 19), (19, 20),
(0, 17),
)
@dataclass
class Hand:
"""One detected hand."""
keypoints: np.ndarray
scores: np.ndarray
box: np.ndarray
conf: float
@property
def scale(self) -> float:
"""Characteristic hand size."""
palm = np.linalg.norm(self.keypoints[MIDDLE_MCP] - self.keypoints[WRIST])
if palm < 1e-3:
palm = max(self.box[2] - self.box[0], self.box[3] - self.box[1]) * 0.5
return float(max(palm, 1e-3))
@property
def center(self) -> np.ndarray:
"""Palm center point."""
return self.keypoints[[WRIST, INDEX_MCP, PINKY_MCP]].mean(axis=0)
def point(self, idx: int) -> np.ndarray:
"""Keypoint by index."""
return self.keypoints[idx]
|