kinemotion 0.70.0__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.

kinemotion/core/pose.py CHANGED
@@ -18,6 +18,8 @@ Configuration strategies for matching Solution API behavior:
18
18
 
19
19
  from __future__ import annotations
20
20
 
21
+ from typing import Any
22
+
21
23
  import cv2
22
24
  import mediapipe as mp
23
25
  import numpy as np
@@ -159,358 +161,51 @@ class MediaPipePoseTracker:
159
161
 
160
162
 
161
163
  class PoseTrackerFactory:
162
- """Factory for creating pose trackers with automatic backend selection.
164
+ """Factory for creating pose trackers.
163
165
 
164
- Supports multiple backends with auto-detection:
165
- - RTMPose CUDA: NVIDIA GPU acceleration (fastest, 133 FPS)
166
- - RTMPose CoreML: Apple Silicon acceleration (42 FPS)
167
- - RTMPose CPU: Optimized CPU implementation (40-68 FPS)
168
- - MediaPipe: Fallback baseline (48 FPS)
166
+ Currently supports MediaPipe as the only backend.
169
167
 
170
168
  Usage:
171
- # Auto-detect best backend
172
169
  tracker = PoseTrackerFactory.create()
173
-
174
- # Force specific backend
175
- tracker = PoseTrackerFactory.create(backend='rtmpose-cuda')
176
-
177
- # Check available backends
178
- available = PoseTrackerFactory.get_available_backends()
179
170
  """
180
171
 
181
- # Backend class mappings
182
- _BACKENDS: dict[str, type] = {}
183
-
184
172
  @classmethod
185
173
  def create(
186
174
  cls,
187
- backend: str = "auto",
188
- mode: str = "lightweight",
189
- **kwargs: object,
190
- ) -> object:
191
- """Create a pose tracker with the specified backend.
192
-
193
- Args:
194
- backend: Backend selection:
195
- - 'auto': Auto-detect best available backend
196
- - 'mediapipe': MediaPipe Tasks API (baseline)
197
- - 'rtmpose-cpu': RTMPose optimized CPU
198
- - 'rtmpose-cuda': RTMPose with CUDA (NVIDIA GPU)
199
- - 'rtmpose-coreml': RTMPose with CoreML (Apple Silicon)
200
- mode: RTMPose performance mode ('lightweight', 'balanced', 'performance')
201
- Only used for RTMPose backends
202
- **kwargs: Additional arguments passed to tracker constructor
203
-
204
- Returns:
205
- Configured pose tracker instance
206
-
207
- Raises:
208
- ValueError: If backend is not available or recognized
209
- """
210
- # Auto-detect backend
211
- if backend == "auto":
212
- backend = cls._detect_best_backend()
213
- backend = cls._check_backend_available(backend)
214
-
215
- # Check environment variable override
216
- import os
217
-
218
- env_backend = os.environ.get("POSE_TRACKER_BACKEND")
219
- if env_backend:
220
- backend = cls._normalize_backend_name(env_backend)
221
-
222
- # Verify backend is available
223
- backend = cls._check_backend_available(backend)
224
-
225
- # Get tracker class
226
- tracker_class = cls._get_tracker_class(backend)
227
-
228
- # Create tracker with appropriate arguments
229
- return cls._create_tracker(tracker_class, backend, mode, kwargs)
230
-
231
- @classmethod
232
- def _detect_best_backend(cls) -> str:
233
- """Detect the best available backend.
234
-
235
- Priority order:
236
- 1. CUDA (NVIDIA GPU) - fastest
237
- 2. CoreML (Apple Silicon) - good performance
238
- 3. RTMPose CPU - optimized CPU
239
- 4. MediaPipe - baseline fallback
240
-
241
- Returns:
242
- Backend name string
243
- """
244
- # Check for CUDA (NVIDIA GPU)
245
- try:
246
- import torch
247
-
248
- if torch.cuda.is_available():
249
- return "rtmpose-cuda"
250
- except ImportError:
251
- pass
252
-
253
- # Check for CoreML (Apple Silicon)
254
- import sys
255
-
256
- if sys.platform == "darwin":
257
- return "rtmpose-coreml"
258
-
259
- # Check for RTMPose CPU
260
- try:
261
- from kinemotion.core.rtmpose_cpu import (
262
- OptimizedCPUTracker as _RTMPoseCPU, # type: ignore
263
- )
264
-
265
- _ = _RTMPoseCPU # Mark as intentionally used for availability check
266
-
267
- return "rtmpose-cpu"
268
- except ImportError:
269
- pass
270
-
271
- # Fallback to MediaPipe
272
- return "mediapipe"
273
-
274
- @classmethod
275
- def _check_backend_available(cls, backend: str) -> str:
276
- """Check if a backend is available and return a fallback if not.
277
-
278
- Args:
279
- backend: Requested backend name
280
-
281
- Returns:
282
- Available backend name (may be different from requested)
283
-
284
- Raises:
285
- ValueError: If no backend is available
286
- """
287
- normalized = cls._normalize_backend_name(backend)
288
-
289
- # Check if specific backend can be imported
290
- if normalized == "rtmpose-cuda":
291
- try:
292
- import torch # noqa: F401
293
-
294
- if not torch.cuda.is_available():
295
- # CUDA not available, fall back to CPU
296
- return cls._check_backend_available("rtmpose-cpu")
297
- # CUDA is available, use rtmpose-cuda
298
- return normalized
299
- except ImportError:
300
- return cls._check_backend_available("rtmpose-cpu")
301
-
302
- if normalized == "rtmpose-coreml":
303
- import sys
304
-
305
- if sys.platform != "darwin":
306
- # Not macOS, fall back to CPU
307
- return cls._check_backend_available("rtmpose-cpu")
308
-
309
- if normalized == "rtmpose-cpu":
310
- try:
311
- from kinemotion.core.rtmpose_cpu import (
312
- OptimizedCPUTracker as _RTMPoseCPU,
313
- ) # type: ignore
314
-
315
- _ = _RTMPoseCPU # Mark as intentionally used for availability check
316
-
317
- return normalized
318
- except ImportError:
319
- # RTMPose not available, fall back to MediaPipe
320
- return "mediapipe"
321
-
322
- if normalized == "mediapipe":
323
- try:
324
- import mediapipe as _mp # noqa: F401
325
-
326
- _ = _mp # Mark as intentionally used for availability check
327
- return normalized
328
- except ImportError as err:
329
- raise ValueError(
330
- "No pose tracking backend available. Please install mediapipe or rtmlib."
331
- ) from err
332
-
333
- raise ValueError(f"Unknown backend: {backend}")
334
-
335
- @classmethod
336
- def _normalize_backend_name(cls, backend: str) -> str:
337
- """Normalize backend name to canonical form.
338
-
339
- Args:
340
- backend: User-provided backend name
341
-
342
- Returns:
343
- Canonical backend name
344
- """
345
- # Normalize various aliases to canonical names
346
- aliases = {
347
- "mp": "mediapipe",
348
- "mediapipe": "mediapipe",
349
- "rtmpose": "rtmpose-cpu",
350
- "rtmpose-cpu": "rtmpose-cpu",
351
- "rtmpose_cpu": "rtmpose-cpu",
352
- "cpu": "rtmpose-cpu",
353
- "cuda": "rtmpose-cuda",
354
- "rtmpose-cuda": "rtmpose-cuda",
355
- "rtmpose_cuda": "rtmpose-cuda",
356
- "gpu": "rtmpose-cuda",
357
- "mps": "rtmpose-coreml",
358
- "coreml": "rtmpose-coreml",
359
- "rtmpose-coreml": "rtmpose-coreml",
360
- "rtmpose_coreml": "rtmpose-coreml",
361
- }
362
- return aliases.get(backend.lower(), backend)
363
-
364
- @classmethod
365
- def _get_tracker_class(cls, backend: str):
366
- """Get the tracker class for a backend.
175
+ backend: str = "mediapipe",
176
+ **kwargs: Any,
177
+ ) -> MediaPipePoseTracker:
178
+ """Create a MediaPipe pose tracker.
367
179
 
368
180
  Args:
369
- backend: Canonical backend name
181
+ backend: Backend selection (only 'mediapipe' supported)
182
+ **kwargs: Arguments passed to MediaPipePoseTracker
370
183
 
371
184
  Returns:
372
- Tracker class
185
+ Configured MediaPipePoseTracker instance
373
186
 
374
187
  Raises:
375
- ValueError: If backend is not recognized
188
+ ValueError: If backend is not 'mediapipe'
376
189
  """
377
- if backend == "mediapipe":
378
- return MediaPipePoseTracker
379
-
380
- if backend == "rtmpose-cpu":
381
- try:
382
- from kinemotion.core.rtmpose_cpu import OptimizedCPUTracker
383
-
384
- return OptimizedCPUTracker
385
- except ImportError as e:
386
- raise ValueError(f"RTMPose CPU backend requested but not available: {e}") from e
190
+ # Normalize and validate backend
191
+ normalized = backend.lower()
192
+ if normalized not in ("mediapipe", "mp", "auto"):
193
+ raise ValueError(f"Unknown backend: {backend}. Only 'mediapipe' is supported.")
387
194
 
388
- if backend in ("rtmpose-cuda", "rtmpose-coreml"):
389
- try:
390
- from kinemotion.core.rtmpose_wrapper import RTMPoseWrapper
195
+ # Filter out any legacy kwargs that don't apply to MediaPipe
196
+ legacy_keys = {"mode", "backend", "device", "pose_input_size"}
197
+ filtered_kwargs = {k: v for k, v in kwargs.items() if k not in legacy_keys}
391
198
 
392
- return RTMPoseWrapper
393
- except ImportError as e:
394
- raise ValueError(
395
- f"RTMPose wrapper backend requested but not available: {e}"
396
- ) from e
397
-
398
- raise ValueError(f"Unknown backend: {backend}")
399
-
400
- @classmethod
401
- def _create_tracker(
402
- cls,
403
- tracker_class: type,
404
- backend: str,
405
- mode: str,
406
- kwargs: dict[str, object],
407
- ) -> object:
408
- """Create a tracker instance with appropriate arguments.
409
-
410
- Args:
411
- tracker_class: Tracker class to instantiate
412
- backend: Backend name (for parameter mapping)
413
- mode: RTMPose mode (only used for RTMPose backends)
414
- kwargs: Additional arguments from user
415
-
416
- Returns:
417
- Tracker instance
418
- """
419
- # MediaPipe-specific arguments
420
- if backend == "mediapipe":
421
- # Remove RTMPose-specific arguments
422
- rttmpose_keys = {"mode", "backend", "device", "pose_input_size"}
423
- filtered_kwargs = {k: v for k, v in kwargs.items() if k not in rttmpose_keys}
424
- return tracker_class(**filtered_kwargs)
425
-
426
- # OptimizedCPUTracker (CPU-only, doesn't accept device parameter)
427
- if backend == "rtmpose-cpu":
428
- # Remove RTMPoseWrapper-specific and MediaPipe-specific arguments
429
- unsupported_keys = {
430
- "backend",
431
- "device",
432
- "min_detection_confidence",
433
- "min_tracking_confidence",
434
- }
435
- filtered_kwargs = {k: v for k, v in kwargs.items() if k not in unsupported_keys}
436
- filtered_kwargs.setdefault("mode", mode)
437
- return tracker_class(**filtered_kwargs)
438
-
439
- # RTMPoseWrapper (CUDA/CoreML, requires device parameter)
440
- # Remove MediaPipe-specific arguments
441
- mediapipe_keys = {"min_detection_confidence", "min_tracking_confidence"}
442
- filtered_kwargs = {k: v for k, v in kwargs.items() if k not in mediapipe_keys}
443
-
444
- device = backend.split("-")[-1] # Extract 'cuda', 'cpu', 'coreml'
445
- if device == "coreml":
446
- device = "mps" # RTMLib uses 'mps' for Apple Silicon
447
-
448
- filtered_kwargs.setdefault("device", device)
449
- filtered_kwargs.setdefault("mode", mode)
450
-
451
- return tracker_class(**filtered_kwargs)
199
+ return MediaPipePoseTracker(**filtered_kwargs)
452
200
 
453
201
  @classmethod
454
202
  def get_available_backends(cls) -> list[str]:
455
- """Get list of available backends on current system.
203
+ """Get list of available backends.
456
204
 
457
205
  Returns:
458
- List of available backend names
206
+ List containing 'mediapipe'
459
207
  """
460
- available = []
461
-
462
- # Always have MediaPipe as fallback
463
- try:
464
- import mediapipe as _mp # noqa: F401
465
-
466
- _ = _mp # Mark as intentionally used for availability check
467
- available.append("mediapipe")
468
- except ImportError:
469
- pass
470
-
471
- # Check RTMPose CPU
472
- try:
473
- from kinemotion.core.rtmpose_cpu import (
474
- OptimizedCPUTracker as _RTMPoseCPU,
475
- ) # type: ignore
476
-
477
- _ = _RTMPoseCPU # Mark as intentionally used for availability check
478
-
479
- available.append("rtmpose-cpu")
480
- except ImportError:
481
- pass
482
-
483
- # Check CUDA
484
- try:
485
- import torch
486
-
487
- if torch.cuda.is_available():
488
- from kinemotion.core.rtmpose_wrapper import (
489
- RTMPoseWrapper as _RTMPoseWrapper,
490
- ) # type: ignore
491
-
492
- _ = _RTMPoseWrapper # Mark as intentionally used for availability check
493
-
494
- available.append("rtmpose-cuda")
495
- except ImportError:
496
- pass
497
-
498
- # Check CoreML (Apple Silicon)
499
- import sys
500
-
501
- if sys.platform == "darwin":
502
- try:
503
- from kinemotion.core.rtmpose_wrapper import (
504
- RTMPoseWrapper as _RTMPoseWrapperMPS,
505
- ) # type: ignore
506
-
507
- _ = _RTMPoseWrapperMPS # Mark as intentionally used for availability check
508
-
509
- available.append("rtmpose-coreml")
510
- except ImportError:
511
- pass
512
-
513
- return available
208
+ return ["mediapipe"]
514
209
 
515
210
  @classmethod
516
211
  def get_backend_info(cls, backend: str) -> dict[str, str]:
@@ -522,39 +217,15 @@ class PoseTrackerFactory:
522
217
  Returns:
523
218
  Dictionary with backend information
524
219
  """
525
- info = {
526
- "mediapipe": {
220
+ if backend.lower() in ("mediapipe", "mp"):
221
+ return {
527
222
  "name": "MediaPipe",
528
- "description": "Baseline pose tracking using MediaPipe Tasks API",
223
+ "description": "Pose tracking using MediaPipe Tasks API",
529
224
  "performance": "~48 FPS",
530
- "accuracy": "Baseline (reference)",
225
+ "accuracy": "Reference (validated for jumps)",
531
226
  "requirements": "mediapipe package",
532
- },
533
- "rtmpose-cpu": {
534
- "name": "RTMPose CPU",
535
- "description": "Optimized CPU implementation with ONNX Runtime",
536
- "performance": "~40-68 FPS (134% of MediaPipe)",
537
- "accuracy": "9-12px mean difference (1-5% metric accuracy)",
538
- "requirements": "rtmlib package",
539
- },
540
- "rtmpose-cuda": {
541
- "name": "RTMPose CUDA",
542
- "description": "NVIDIA GPU acceleration with CUDA",
543
- "performance": "~133 FPS (271% of MediaPipe)",
544
- "accuracy": "9-12px mean difference (1-5% metric accuracy)",
545
- "requirements": "rtmlib + CUDA-capable GPU",
546
- },
547
- "rtmpose-coreml": {
548
- "name": "RTMPose CoreML",
549
- "description": "Apple Silicon acceleration with CoreML",
550
- "performance": "~42 FPS (94% of MediaPipe)",
551
- "accuracy": "9-12px mean difference (1-5% metric accuracy)",
552
- "requirements": "rtmlib + Apple Silicon",
553
- },
554
- }
555
-
556
- normalized = cls._normalize_backend_name(backend)
557
- return info.get(normalized, {})
227
+ }
228
+ return {}
558
229
 
559
230
 
560
231
  def get_tracker_info(tracker: object) -> str:
@@ -571,50 +242,8 @@ def get_tracker_info(tracker: object) -> str:
571
242
 
572
243
  info = f"{tracker_class} (from {module})"
573
244
 
574
- # Add backend-specific details
575
245
  if tracker_class == "MediaPipePoseTracker":
576
246
  info += " [MediaPipe Tasks API]"
577
- elif tracker_class == "OptimizedCPUTracker":
578
- # Check if ONNX Runtime has CUDA
579
- try:
580
- import onnxruntime as ort
581
-
582
- providers = ort.get_available_providers()
583
- if "CUDAExecutionProvider" in providers:
584
- # Check what providers the session is actually using
585
- det_session = getattr(tracker, "det_session", None)
586
- if det_session is not None:
587
- active_providers = det_session.get_providers()
588
- if "CUDAExecutionProvider" in active_providers:
589
- info += " [ONNX Runtime: CUDA]"
590
- else:
591
- info += " [ONNX Runtime: CPU]"
592
- else:
593
- info += " [ONNX Runtime]"
594
- else:
595
- info += " [ONNX Runtime: CPU]"
596
- except ImportError:
597
- info += " [ONNX Runtime]"
598
- elif tracker_class == "RTMPoseWrapper":
599
- device = getattr(tracker, "device", None)
600
- if device:
601
- if device == "cuda":
602
- try:
603
- import torch
604
-
605
- if torch.cuda.is_available():
606
- device_name = torch.cuda.get_device_name(0)
607
- info += f" [PyTorch CUDA: {device_name}]"
608
- else:
609
- info += " [PyTorch: CPU fallback]"
610
- except ImportError:
611
- info += " [PyTorch CUDA]"
612
- elif device == "mps":
613
- info += " [PyTorch: Apple Silicon GPU]"
614
- else:
615
- info += f" [PyTorch: {device}]"
616
- else:
617
- info += " [PyTorch]"
618
247
 
619
248
  return info
620
249
 
@@ -90,7 +90,6 @@ class DropJumpVideoConfig:
90
90
  overrides: AnalysisOverrides | None = None
91
91
  detection_confidence: float | None = None
92
92
  tracking_confidence: float | None = None
93
- pose_backend: str | None = None
94
93
 
95
94
 
96
95
  def _assess_dropjump_quality(
@@ -237,7 +236,6 @@ def _setup_pose_tracker(
237
236
  detection_confidence: float | None,
238
237
  tracking_confidence: float | None,
239
238
  pose_tracker: "MediaPipePoseTracker | None",
240
- pose_backend: str | None,
241
239
  timer: Timer,
242
240
  verbose: bool = False,
243
241
  ) -> tuple["MediaPipePoseTracker", bool]:
@@ -250,29 +248,13 @@ def _setup_pose_tracker(
250
248
  should_close_tracker = False
251
249
 
252
250
  if tracker is None:
253
- if pose_backend is not None:
254
- import time
255
-
256
- from ..core import get_tracker_info
257
- from ..core.pose import PoseTrackerFactory
258
-
259
- init_start = time.perf_counter()
260
- tracker = PoseTrackerFactory.create(
261
- backend=pose_backend,
262
- timer=timer,
263
- )
264
- init_time = time.perf_counter() - init_start
265
-
266
- if verbose:
267
- print(f"Using pose backend: {pose_backend}")
268
- print(f" → {get_tracker_info(tracker)}")
269
- print(f" → Initialized in {init_time * 1000:.1f} ms")
270
- else:
271
- tracker = MediaPipePoseTracker(
272
- min_detection_confidence=detection_conf,
273
- min_tracking_confidence=tracking_conf,
274
- timer=timer,
275
- )
251
+ if verbose:
252
+ print("Processing all frames with MediaPipe pose tracking...")
253
+ tracker = MediaPipePoseTracker(
254
+ min_detection_confidence=detection_conf,
255
+ min_tracking_confidence=tracking_conf,
256
+ timer=timer,
257
+ )
276
258
  should_close_tracker = True
277
259
 
278
260
  return tracker, should_close_tracker
@@ -509,7 +491,6 @@ def process_dropjump_video(
509
491
  verbose: bool = False,
510
492
  timer: Timer | None = None,
511
493
  pose_tracker: "MediaPipePoseTracker | None" = None,
512
- pose_backend: str | None = None,
513
494
  ) -> DropJumpMetrics:
514
495
  """
515
496
  Process a single drop jump video and return metrics.
@@ -554,7 +535,6 @@ def process_dropjump_video(
554
535
  detection_confidence,
555
536
  tracking_confidence,
556
537
  pose_tracker,
557
- pose_backend,
558
538
  timer,
559
539
  verbose,
560
540
  )
@@ -31,7 +31,6 @@ class AnalysisParameters:
31
31
  visibility_threshold: float | None = None
32
32
  detection_confidence: float | None = None
33
33
  tracking_confidence: float | None = None
34
- pose_backend: str | None = None
35
34
 
36
35
 
37
36
  @click.command(name="dropjump-analyze")
@@ -66,23 +65,6 @@ class AnalysisParameters:
66
65
  is_flag=True,
67
66
  help="Show auto-selected parameters and analysis details",
68
67
  )
69
- @click.option(
70
- "--pose-backend",
71
- type=click.Choice(
72
- ["auto", "mediapipe", "rtmpose-cpu", "rtmpose-cuda", "rtmpose-coreml"],
73
- case_sensitive=False,
74
- ),
75
- default="auto",
76
- help=(
77
- "Pose tracking backend: "
78
- "auto (detect best), "
79
- "mediapipe (baseline), "
80
- "rtmpose-cpu (optimized CPU), "
81
- "rtmpose-cuda (NVIDIA GPU), "
82
- "rtmpose-coreml (Apple Silicon)"
83
- ),
84
- show_default=True,
85
- )
86
68
  # Batch processing options
87
69
  @click.option(
88
70
  "--batch",
@@ -161,7 +143,6 @@ def dropjump_analyze( # NOSONAR(S107) - Click CLI requires individual
161
143
  json_output: str | None,
162
144
  quality: str,
163
145
  verbose: bool,
164
- pose_backend: str,
165
146
  batch: bool,
166
147
  workers: int,
167
148
  output_dir: str | None,
@@ -231,7 +212,6 @@ def dropjump_analyze( # NOSONAR(S107) - Click CLI requires individual
231
212
  json_output_dir,
232
213
  csv_summary,
233
214
  expert_params,
234
- pose_backend,
235
215
  )
236
216
  else:
237
217
  # Single video mode (original behavior)
@@ -242,7 +222,6 @@ def dropjump_analyze( # NOSONAR(S107) - Click CLI requires individual
242
222
  quality,
243
223
  verbose,
244
224
  expert_params,
245
- pose_backend,
246
225
  )
247
226
 
248
227
 
@@ -253,7 +232,6 @@ def _process_single(
253
232
  quality: str,
254
233
  verbose: bool,
255
234
  expert_params: AnalysisParameters,
256
- pose_backend: str,
257
235
  ) -> None:
258
236
  """Process a single video by calling the API."""
259
237
  click.echo(f"Analyzing video: {video_path}", err=True)
@@ -288,7 +266,6 @@ def _process_single(
288
266
  overrides=overrides,
289
267
  detection_confidence=expert_params.detection_confidence,
290
268
  tracking_confidence=expert_params.tracking_confidence,
291
- pose_backend=pose_backend,
292
269
  verbose=verbose,
293
270
  )
294
271
 
@@ -332,7 +309,6 @@ def _create_video_configs(
332
309
  output_dir: str | None,
333
310
  json_output_dir: str | None,
334
311
  expert_params: AnalysisParameters,
335
- pose_backend: str,
336
312
  ) -> list[DropJumpVideoConfig]:
337
313
  """Build configuration objects for each video.
338
314
 
@@ -380,7 +356,6 @@ def _create_video_configs(
380
356
  overrides=overrides,
381
357
  detection_confidence=expert_params.detection_confidence,
382
358
  tracking_confidence=expert_params.tracking_confidence,
383
- pose_backend=expert_params.pose_backend,
384
359
  )
385
360
  configs.append(config)
386
361
 
@@ -545,7 +520,6 @@ def _process_batch(
545
520
  json_output_dir: str | None,
546
521
  csv_summary: str | None,
547
522
  expert_params: AnalysisParameters,
548
- pose_backend: str,
549
523
  ) -> None:
550
524
  """Process multiple videos in batch mode using parallel processing."""
551
525
  click.echo(f"\nBatch processing {len(video_files)} videos with {workers} workers", err=True)
@@ -556,7 +530,7 @@ def _process_batch(
556
530
 
557
531
  # Create video configurations
558
532
  configs = _create_video_configs(
559
- video_files, quality, output_dir, json_output_dir, expert_params, pose_backend
533
+ video_files, quality, output_dir, json_output_dir, expert_params
560
534
  )
561
535
 
562
536
  # Progress callback
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kinemotion
3
- Version: 0.70.0
3
+ Version: 0.71.0
4
4
  Summary: Video-based kinematic analysis for athletic performance
5
5
  Project-URL: Homepage, https://github.com/feniix/kinemotion
6
6
  Project-URL: Repository, https://github.com/feniix/kinemotion
@@ -23,12 +23,9 @@ Requires-Python: <3.13,>=3.10
23
23
  Requires-Dist: click>=8.1.7
24
24
  Requires-Dist: mediapipe>=0.10.30
25
25
  Requires-Dist: numpy>=1.26.0
26
- Requires-Dist: onnxruntime-gpu>=1.23.2
27
26
  Requires-Dist: opencv-python>=4.9.0
28
27
  Requires-Dist: platformdirs>=4.0.0
29
- Requires-Dist: rtmlib>=0.0.13
30
28
  Requires-Dist: scipy>=1.11.0
31
- Requires-Dist: torch>=2.0.0
32
29
  Requires-Dist: tqdm>=4.67.1
33
30
  Requires-Dist: typing-extensions>=4.15.0
34
31
  Description-Content-Type: text/markdown