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.

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,368 +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
- # On macOS, verify CoreML wrapper is available
310
- try:
311
- from kinemotion.core.rtmpose_wrapper import RTMPoseWrapper
312
-
313
- _ = RTMPoseWrapper # Mark as intentionally used
314
- return normalized
315
- except ImportError:
316
- # CoreML wrapper not available, fall back to CPU
317
- return cls._check_backend_available("rtmpose-cpu")
318
-
319
- if normalized == "rtmpose-cpu":
320
- try:
321
- from kinemotion.core.rtmpose_cpu import (
322
- OptimizedCPUTracker as _RTMPoseCPU,
323
- ) # type: ignore
324
-
325
- _ = _RTMPoseCPU # Mark as intentionally used for availability check
326
-
327
- return normalized
328
- except ImportError:
329
- # RTMPose not available, fall back to MediaPipe
330
- return "mediapipe"
331
-
332
- if normalized == "mediapipe":
333
- try:
334
- import mediapipe as _mp # noqa: F401
335
-
336
- _ = _mp # Mark as intentionally used for availability check
337
- return normalized
338
- except ImportError as err:
339
- raise ValueError(
340
- "No pose tracking backend available. Please install mediapipe or rtmlib."
341
- ) from err
342
-
343
- raise ValueError(f"Unknown backend: {backend}")
344
-
345
- @classmethod
346
- def _normalize_backend_name(cls, backend: str) -> str:
347
- """Normalize backend name to canonical form.
348
-
349
- Args:
350
- backend: User-provided backend name
351
-
352
- Returns:
353
- Canonical backend name
354
- """
355
- # Normalize various aliases to canonical names
356
- aliases = {
357
- "mp": "mediapipe",
358
- "mediapipe": "mediapipe",
359
- "rtmpose": "rtmpose-cpu",
360
- "rtmpose-cpu": "rtmpose-cpu",
361
- "rtmpose_cpu": "rtmpose-cpu",
362
- "cpu": "rtmpose-cpu",
363
- "cuda": "rtmpose-cuda",
364
- "rtmpose-cuda": "rtmpose-cuda",
365
- "rtmpose_cuda": "rtmpose-cuda",
366
- "gpu": "rtmpose-cuda",
367
- "mps": "rtmpose-coreml",
368
- "coreml": "rtmpose-coreml",
369
- "rtmpose-coreml": "rtmpose-coreml",
370
- "rtmpose_coreml": "rtmpose-coreml",
371
- }
372
- return aliases.get(backend.lower(), backend)
373
-
374
- @classmethod
375
- def _get_tracker_class(cls, backend: str):
376
- """Get the tracker class for a backend.
175
+ backend: str = "mediapipe",
176
+ **kwargs: Any,
177
+ ) -> MediaPipePoseTracker:
178
+ """Create a MediaPipe pose tracker.
377
179
 
378
180
  Args:
379
- backend: Canonical backend name
181
+ backend: Backend selection (only 'mediapipe' supported)
182
+ **kwargs: Arguments passed to MediaPipePoseTracker
380
183
 
381
184
  Returns:
382
- Tracker class
185
+ Configured MediaPipePoseTracker instance
383
186
 
384
187
  Raises:
385
- ValueError: If backend is not recognized
188
+ ValueError: If backend is not 'mediapipe'
386
189
  """
387
- if backend == "mediapipe":
388
- return MediaPipePoseTracker
389
-
390
- if backend == "rtmpose-cpu":
391
- try:
392
- from kinemotion.core.rtmpose_cpu import OptimizedCPUTracker
393
-
394
- return OptimizedCPUTracker
395
- except ImportError as e:
396
- 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.")
397
194
 
398
- if backend in ("rtmpose-cuda", "rtmpose-coreml"):
399
- try:
400
- 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}
401
198
 
402
- return RTMPoseWrapper
403
- except ImportError as e:
404
- raise ValueError(
405
- f"RTMPose wrapper backend requested but not available: {e}"
406
- ) from e
407
-
408
- raise ValueError(f"Unknown backend: {backend}")
409
-
410
- @classmethod
411
- def _create_tracker(
412
- cls,
413
- tracker_class: type,
414
- backend: str,
415
- mode: str,
416
- kwargs: dict[str, object],
417
- ) -> object:
418
- """Create a tracker instance with appropriate arguments.
419
-
420
- Args:
421
- tracker_class: Tracker class to instantiate
422
- backend: Backend name (for parameter mapping)
423
- mode: RTMPose mode (only used for RTMPose backends)
424
- kwargs: Additional arguments from user
425
-
426
- Returns:
427
- Tracker instance
428
- """
429
- # MediaPipe-specific arguments
430
- if backend == "mediapipe":
431
- # Remove RTMPose-specific arguments
432
- rttmpose_keys = {"mode", "backend", "device", "pose_input_size"}
433
- filtered_kwargs = {k: v for k, v in kwargs.items() if k not in rttmpose_keys}
434
- return tracker_class(**filtered_kwargs)
435
-
436
- # OptimizedCPUTracker (CPU-only, doesn't accept device parameter)
437
- if backend == "rtmpose-cpu":
438
- # Remove RTMPoseWrapper-specific and MediaPipe-specific arguments
439
- unsupported_keys = {
440
- "backend",
441
- "device",
442
- "min_detection_confidence",
443
- "min_tracking_confidence",
444
- }
445
- filtered_kwargs = {k: v for k, v in kwargs.items() if k not in unsupported_keys}
446
- filtered_kwargs.setdefault("mode", mode)
447
- return tracker_class(**filtered_kwargs)
448
-
449
- # RTMPoseWrapper (CUDA/CoreML, requires device parameter)
450
- # Remove MediaPipe-specific arguments
451
- mediapipe_keys = {"min_detection_confidence", "min_tracking_confidence"}
452
- filtered_kwargs = {k: v for k, v in kwargs.items() if k not in mediapipe_keys}
453
-
454
- device = backend.split("-")[-1] # Extract 'cuda', 'cpu', 'coreml'
455
- if device == "coreml":
456
- device = "mps" # RTMLib uses 'mps' for Apple Silicon
457
-
458
- filtered_kwargs.setdefault("device", device)
459
- filtered_kwargs.setdefault("mode", mode)
460
-
461
- return tracker_class(**filtered_kwargs)
199
+ return MediaPipePoseTracker(**filtered_kwargs)
462
200
 
463
201
  @classmethod
464
202
  def get_available_backends(cls) -> list[str]:
465
- """Get list of available backends on current system.
203
+ """Get list of available backends.
466
204
 
467
205
  Returns:
468
- List of available backend names
206
+ List containing 'mediapipe'
469
207
  """
470
- available = []
471
-
472
- # Always have MediaPipe as fallback
473
- try:
474
- import mediapipe as _mp # noqa: F401
475
-
476
- _ = _mp # Mark as intentionally used for availability check
477
- available.append("mediapipe")
478
- except ImportError:
479
- pass
480
-
481
- # Check RTMPose CPU
482
- try:
483
- from kinemotion.core.rtmpose_cpu import (
484
- OptimizedCPUTracker as _RTMPoseCPU,
485
- ) # type: ignore
486
-
487
- _ = _RTMPoseCPU # Mark as intentionally used for availability check
488
-
489
- available.append("rtmpose-cpu")
490
- except ImportError:
491
- pass
492
-
493
- # Check CUDA
494
- try:
495
- import torch
496
-
497
- if torch.cuda.is_available():
498
- from kinemotion.core.rtmpose_wrapper import (
499
- RTMPoseWrapper as _RTMPoseWrapper,
500
- ) # type: ignore
501
-
502
- _ = _RTMPoseWrapper # Mark as intentionally used for availability check
503
-
504
- available.append("rtmpose-cuda")
505
- except ImportError:
506
- pass
507
-
508
- # Check CoreML (Apple Silicon)
509
- import sys
510
-
511
- if sys.platform == "darwin":
512
- try:
513
- from kinemotion.core.rtmpose_wrapper import (
514
- RTMPoseWrapper as _RTMPoseWrapperMPS,
515
- ) # type: ignore
516
-
517
- _ = _RTMPoseWrapperMPS # Mark as intentionally used for availability check
518
-
519
- available.append("rtmpose-coreml")
520
- except ImportError:
521
- pass
522
-
523
- return available
208
+ return ["mediapipe"]
524
209
 
525
210
  @classmethod
526
211
  def get_backend_info(cls, backend: str) -> dict[str, str]:
@@ -532,39 +217,15 @@ class PoseTrackerFactory:
532
217
  Returns:
533
218
  Dictionary with backend information
534
219
  """
535
- info = {
536
- "mediapipe": {
220
+ if backend.lower() in ("mediapipe", "mp"):
221
+ return {
537
222
  "name": "MediaPipe",
538
- "description": "Baseline pose tracking using MediaPipe Tasks API",
223
+ "description": "Pose tracking using MediaPipe Tasks API",
539
224
  "performance": "~48 FPS",
540
- "accuracy": "Baseline (reference)",
225
+ "accuracy": "Reference (validated for jumps)",
541
226
  "requirements": "mediapipe package",
542
- },
543
- "rtmpose-cpu": {
544
- "name": "RTMPose CPU",
545
- "description": "Optimized CPU implementation with ONNX Runtime",
546
- "performance": "~40-68 FPS (134% of MediaPipe)",
547
- "accuracy": "9-12px mean difference (1-5% metric accuracy)",
548
- "requirements": "rtmlib package",
549
- },
550
- "rtmpose-cuda": {
551
- "name": "RTMPose CUDA",
552
- "description": "NVIDIA GPU acceleration with CUDA",
553
- "performance": "~133 FPS (271% of MediaPipe)",
554
- "accuracy": "9-12px mean difference (1-5% metric accuracy)",
555
- "requirements": "rtmlib + CUDA-capable GPU",
556
- },
557
- "rtmpose-coreml": {
558
- "name": "RTMPose CoreML",
559
- "description": "Apple Silicon acceleration with CoreML",
560
- "performance": "~42 FPS (94% of MediaPipe)",
561
- "accuracy": "9-12px mean difference (1-5% metric accuracy)",
562
- "requirements": "rtmlib + Apple Silicon",
563
- },
564
- }
565
-
566
- normalized = cls._normalize_backend_name(backend)
567
- return info.get(normalized, {})
227
+ }
228
+ return {}
568
229
 
569
230
 
570
231
  def get_tracker_info(tracker: object) -> str:
@@ -581,50 +242,8 @@ def get_tracker_info(tracker: object) -> str:
581
242
 
582
243
  info = f"{tracker_class} (from {module})"
583
244
 
584
- # Add backend-specific details
585
245
  if tracker_class == "MediaPipePoseTracker":
586
246
  info += " [MediaPipe Tasks API]"
587
- elif tracker_class == "OptimizedCPUTracker":
588
- # Check if ONNX Runtime has CUDA
589
- try:
590
- import onnxruntime as ort
591
-
592
- providers = ort.get_available_providers()
593
- if "CUDAExecutionProvider" in providers:
594
- # Check what providers the session is actually using
595
- det_session = getattr(tracker, "det_session", None)
596
- if det_session is not None:
597
- active_providers = det_session.get_providers()
598
- if "CUDAExecutionProvider" in active_providers:
599
- info += " [ONNX Runtime: CUDA]"
600
- else:
601
- info += " [ONNX Runtime: CPU]"
602
- else:
603
- info += " [ONNX Runtime]"
604
- else:
605
- info += " [ONNX Runtime: CPU]"
606
- except ImportError:
607
- info += " [ONNX Runtime]"
608
- elif tracker_class == "RTMPoseWrapper":
609
- device = getattr(tracker, "device", None)
610
- if device:
611
- if device == "cuda":
612
- try:
613
- import torch
614
-
615
- if torch.cuda.is_available():
616
- device_name = torch.cuda.get_device_name(0)
617
- info += f" [PyTorch CUDA: {device_name}]"
618
- else:
619
- info += " [PyTorch: CPU fallback]"
620
- except ImportError:
621
- info += " [PyTorch CUDA]"
622
- elif device == "mps":
623
- info += " [PyTorch: Apple Silicon GPU]"
624
- else:
625
- info += f" [PyTorch: {device}]"
626
- else:
627
- info += " [PyTorch]"
628
247
 
629
248
  return info
630
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.1
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,13 +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; sys_platform == 'linux' and platform_machine == 'x86_64'
27
- Requires-Dist: onnxruntime>=1.23.2; sys_platform != 'linux' or platform_machine != 'x86_64'
28
26
  Requires-Dist: opencv-python>=4.9.0
29
27
  Requires-Dist: platformdirs>=4.0.0
30
- Requires-Dist: rtmlib>=0.0.13
31
28
  Requires-Dist: scipy>=1.11.0
32
- Requires-Dist: torch>=2.0.0
33
29
  Requires-Dist: tqdm>=4.67.1
34
30
  Requires-Dist: typing-extensions>=4.15.0
35
31
  Description-Content-Type: text/markdown