kinemotion 0.70.1__py3-none-any.whl → 0.71.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of kinemotion might be problematic. Click here for more details.

@@ -1,190 +0,0 @@
1
- """RTMPose wrapper for CUDA and CoreML acceleration.
2
-
3
- This adapter wraps RTMLib's BodyWithFeet for CUDA (NVIDIA GPU) and CoreML (Apple Silicon)
4
- acceleration, matching kinemotion's PoseTracker API.
5
-
6
- Performance:
7
- - CUDA (RTX 4070 Ti Super): 133 FPS (271% of MediaPipe)
8
- - CoreML (M1 Pro): 42 FPS (94% of MediaPipe)
9
- - Accuracy: 9-12px mean difference from MediaPipe
10
- """
11
-
12
- from __future__ import annotations
13
-
14
- import numpy as np
15
- from rtmlib import BodyWithFeet
16
-
17
- from kinemotion.core.timing import NULL_TIMER, Timer
18
-
19
- # Halpe-26 to kinemotion landmark mapping
20
- HALPE_TO_KINEMOTION = {
21
- 0: "nose",
22
- 5: "left_shoulder",
23
- 6: "right_shoulder",
24
- 11: "left_hip",
25
- 12: "right_hip",
26
- 13: "left_knee",
27
- 14: "right_knee",
28
- 15: "left_ankle",
29
- 16: "right_ankle",
30
- 20: "left_foot_index",
31
- 21: "right_foot_index",
32
- 24: "left_heel",
33
- 25: "right_heel",
34
- }
35
-
36
-
37
- class RTMPoseWrapper:
38
- """RTMPose wrapper for CUDA/CoreML acceleration.
39
-
40
- Uses RTMLib's BodyWithFeet (Halpe-26 format) which provides all 13
41
- kinemotion landmarks including feet.
42
-
43
- Supports:
44
- - device='cuda': NVIDIA GPU acceleration (fastest)
45
- - device='mps': Apple Silicon CoreML acceleration
46
- - device='cpu': Fallback (unoptimized, use rtmpose_cpu.py instead)
47
-
48
- Attributes:
49
- timer: Optional Timer for measuring operations
50
- estimator: RTMLib BodyWithFeet estimator instance
51
- mode: RTMLib mode ('lightweight', 'balanced', 'performance')
52
- device: Target device ('cuda', 'mps', 'cpu')
53
- """
54
-
55
- def __init__(
56
- self,
57
- min_detection_confidence: float = 0.5,
58
- min_tracking_confidence: float = 0.5,
59
- timer: Timer | None = None,
60
- mode: str = "lightweight",
61
- backend: str = "onnxruntime",
62
- device: str = "cpu",
63
- pose_input_size: tuple[int, int] | None = None,
64
- ) -> None:
65
- """Initialize the RTMPose wrapper.
66
-
67
- Args:
68
- min_detection_confidence: Minimum confidence for pose detection
69
- min_tracking_confidence: Minimum confidence for pose tracking
70
- timer: Optional Timer for measuring operations
71
- mode: RTMLib performance mode:
72
- - 'lightweight': Fastest, RTMPose-s
73
- - 'balanced': Default mode
74
- - 'performance': Best accuracy, RTMPose-m
75
- backend: RTMLib backend ('onnxruntime', 'opencv')
76
- device: RTMLib device ('cpu', 'cuda', 'mps')
77
- pose_input_size: Custom input size as (height, width) tuple
78
- """
79
- self.timer = timer or NULL_TIMER
80
- self.mode = mode
81
- self.backend = backend
82
- self.device = device
83
-
84
- with self.timer.measure("rtmpose_wrapper_initialization"):
85
- kwargs = {
86
- "mode": mode,
87
- "backend": backend,
88
- "device": device,
89
- }
90
- if pose_input_size is not None:
91
- kwargs["pose_input_size"] = pose_input_size # type: ignore[assignment]
92
- self.estimator = BodyWithFeet(**kwargs) # type: ignore[arg-type]
93
-
94
- def process_frame(
95
- self, frame: np.ndarray, timestamp_ms: int = 0
96
- ) -> dict[str, tuple[float, float, float]] | None:
97
- """Process a single frame and extract pose landmarks.
98
-
99
- Args:
100
- frame: BGR image frame (OpenCV format)
101
- timestamp_ms: Frame timestamp in milliseconds (unused, for API compatibility)
102
-
103
- Returns:
104
- Dictionary mapping landmark names to (x, y, visibility) tuples,
105
- or None if no pose detected. Coordinates are normalized (0-1).
106
- """
107
- if frame.size == 0:
108
- return None
109
-
110
- height, width = frame.shape[:2]
111
-
112
- # RTMLib expects RGB, but BodyWithFeet handles conversion internally
113
- with self.timer.measure("rtmpose_inference"):
114
- keypoints, scores = self.estimator(frame)
115
-
116
- if keypoints.shape[0] == 0:
117
- return None
118
-
119
- # Extract first person's keypoints
120
- with self.timer.measure("landmark_extraction"):
121
- landmarks = self._extract_landmarks(keypoints[0], scores[0], width, height)
122
-
123
- return landmarks
124
-
125
- def _extract_landmarks(
126
- self,
127
- keypoints: np.ndarray,
128
- scores: np.ndarray,
129
- img_width: int,
130
- img_height: int,
131
- ) -> dict[str, tuple[float, float, float]]:
132
- """Extract and convert RTMLib landmarks to MediaPipe format.
133
-
134
- Args:
135
- keypoints: (26, 2) array of pixel coordinates
136
- scores: (26,) array of confidence scores
137
- img_width: Image width for normalization
138
- img_height: Image height for normalization
139
-
140
- Returns:
141
- Dictionary mapping kinemotion landmark names to normalized
142
- (x, y, visibility) tuples.
143
- """
144
- landmarks = {}
145
-
146
- for halpe_idx, name in HALPE_TO_KINEMOTION.items():
147
- x_pixel, y_pixel = keypoints[halpe_idx]
148
- confidence = float(scores[halpe_idx])
149
-
150
- # Normalize to [0, 1] like MediaPipe
151
- x_norm = float(x_pixel / img_width)
152
- y_norm = float(y_pixel / img_height)
153
-
154
- # Clamp to valid range
155
- x_norm = max(0.0, min(1.0, x_norm))
156
- y_norm = max(0.0, min(1.0, y_norm))
157
-
158
- # Use confidence as visibility (MediaPipe compatibility)
159
- landmarks[name] = (x_norm, y_norm, confidence)
160
-
161
- return landmarks
162
-
163
- def close(self) -> None:
164
- """Release resources (no-op for RTMLib)."""
165
- pass
166
-
167
-
168
- def create_rtmpose_wrapper(
169
- device: str = "cpu",
170
- mode: str = "lightweight",
171
- timer: Timer | None = None,
172
- ) -> RTMPoseWrapper:
173
- """Factory function to create an RTMPose wrapper.
174
-
175
- Args:
176
- device: Target device ('cuda', 'mps', 'cpu')
177
- mode: Performance mode ('lightweight', 'balanced', 'performance')
178
- timer: Optional Timer for measuring operations
179
-
180
- Returns:
181
- Configured RTMPoseWrapper instance
182
-
183
- Example:
184
- # CUDA (NVIDIA GPU)
185
- tracker = create_rtmpose_wrapper(device='cuda')
186
-
187
- # CoreML (Apple Silicon)
188
- tracker = create_rtmpose_wrapper(device='mps')
189
- """
190
- return RTMPoseWrapper(device=device, mode=mode, timer=timer)