kinemotion 0.11.2__tar.gz → 0.11.4__tar.gz

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.

Files changed (70) hide show
  1. {kinemotion-0.11.2 → kinemotion-0.11.4}/CHANGELOG.md +19 -0
  2. {kinemotion-0.11.2 → kinemotion-0.11.4}/PKG-INFO +1 -1
  3. {kinemotion-0.11.2 → kinemotion-0.11.4}/pyproject.toml +1 -1
  4. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/api.py +0 -4
  5. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/cmj/cli.py +8 -79
  6. kinemotion-0.11.4/src/kinemotion/core/cli_utils.py +113 -0
  7. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/dropjump/cli.py +8 -103
  8. {kinemotion-0.11.2 → kinemotion-0.11.4}/uv.lock +1 -1
  9. {kinemotion-0.11.2 → kinemotion-0.11.4}/.dockerignore +0 -0
  10. {kinemotion-0.11.2 → kinemotion-0.11.4}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  11. {kinemotion-0.11.2 → kinemotion-0.11.4}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  12. {kinemotion-0.11.2 → kinemotion-0.11.4}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  13. {kinemotion-0.11.2 → kinemotion-0.11.4}/.github/pull_request_template.md +0 -0
  14. {kinemotion-0.11.2 → kinemotion-0.11.4}/.github/workflows/release.yml +0 -0
  15. {kinemotion-0.11.2 → kinemotion-0.11.4}/.gitignore +0 -0
  16. {kinemotion-0.11.2 → kinemotion-0.11.4}/.pre-commit-config.yaml +0 -0
  17. {kinemotion-0.11.2 → kinemotion-0.11.4}/.tool-versions +0 -0
  18. {kinemotion-0.11.2 → kinemotion-0.11.4}/CLAUDE.md +0 -0
  19. {kinemotion-0.11.2 → kinemotion-0.11.4}/CODE_OF_CONDUCT.md +0 -0
  20. {kinemotion-0.11.2 → kinemotion-0.11.4}/CONTRIBUTING.md +0 -0
  21. {kinemotion-0.11.2 → kinemotion-0.11.4}/Dockerfile +0 -0
  22. {kinemotion-0.11.2 → kinemotion-0.11.4}/GEMINI.md +0 -0
  23. {kinemotion-0.11.2 → kinemotion-0.11.4}/LICENSE +0 -0
  24. {kinemotion-0.11.2 → kinemotion-0.11.4}/README.md +0 -0
  25. {kinemotion-0.11.2 → kinemotion-0.11.4}/SECURITY.md +0 -0
  26. {kinemotion-0.11.2 → kinemotion-0.11.4}/docs/BULK_PROCESSING.md +0 -0
  27. {kinemotion-0.11.2 → kinemotion-0.11.4}/docs/CAMERA_SETUP.md +0 -0
  28. {kinemotion-0.11.2 → kinemotion-0.11.4}/docs/CAMERA_SETUP_ES.md +0 -0
  29. {kinemotion-0.11.2 → kinemotion-0.11.4}/docs/CMJ_GUIDE.md +0 -0
  30. {kinemotion-0.11.2 → kinemotion-0.11.4}/docs/ERRORS_FINDINGS.md +0 -0
  31. {kinemotion-0.11.2 → kinemotion-0.11.4}/docs/FRAMERATE.md +0 -0
  32. {kinemotion-0.11.2 → kinemotion-0.11.4}/docs/IMU_METADATA_PRESERVATION.md +0 -0
  33. {kinemotion-0.11.2 → kinemotion-0.11.4}/docs/PARAMETERS.md +0 -0
  34. {kinemotion-0.11.2 → kinemotion-0.11.4}/docs/REAL_TIME_ANALYSIS.md +0 -0
  35. {kinemotion-0.11.2 → kinemotion-0.11.4}/docs/TRIPLE_EXTENSION.md +0 -0
  36. {kinemotion-0.11.2 → kinemotion-0.11.4}/docs/VALIDATION_PLAN.md +0 -0
  37. {kinemotion-0.11.2 → kinemotion-0.11.4}/examples/bulk/README.md +0 -0
  38. {kinemotion-0.11.2 → kinemotion-0.11.4}/examples/bulk/bulk_processing.py +0 -0
  39. {kinemotion-0.11.2 → kinemotion-0.11.4}/examples/bulk/simple_example.py +0 -0
  40. {kinemotion-0.11.2 → kinemotion-0.11.4}/examples/programmatic_usage.py +0 -0
  41. {kinemotion-0.11.2 → kinemotion-0.11.4}/samples/cmjs/README.md +0 -0
  42. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/__init__.py +0 -0
  43. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/cli.py +0 -0
  44. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/cmj/__init__.py +0 -0
  45. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/cmj/analysis.py +0 -0
  46. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/cmj/debug_overlay.py +0 -0
  47. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/cmj/joint_angles.py +0 -0
  48. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/cmj/kinematics.py +0 -0
  49. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/core/__init__.py +0 -0
  50. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/core/auto_tuning.py +0 -0
  51. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/core/filtering.py +0 -0
  52. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/core/pose.py +0 -0
  53. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/core/smoothing.py +0 -0
  54. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/core/video_io.py +0 -0
  55. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/dropjump/__init__.py +0 -0
  56. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/dropjump/analysis.py +0 -0
  57. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/dropjump/debug_overlay.py +0 -0
  58. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/dropjump/kinematics.py +0 -0
  59. {kinemotion-0.11.2 → kinemotion-0.11.4}/src/kinemotion/py.typed +0 -0
  60. {kinemotion-0.11.2 → kinemotion-0.11.4}/tests/__init__.py +0 -0
  61. {kinemotion-0.11.2 → kinemotion-0.11.4}/tests/test_adaptive_threshold.py +0 -0
  62. {kinemotion-0.11.2 → kinemotion-0.11.4}/tests/test_api.py +0 -0
  63. {kinemotion-0.11.2 → kinemotion-0.11.4}/tests/test_aspect_ratio.py +0 -0
  64. {kinemotion-0.11.2 → kinemotion-0.11.4}/tests/test_cmj_analysis.py +0 -0
  65. {kinemotion-0.11.2 → kinemotion-0.11.4}/tests/test_cmj_kinematics.py +0 -0
  66. {kinemotion-0.11.2 → kinemotion-0.11.4}/tests/test_com_estimation.py +0 -0
  67. {kinemotion-0.11.2 → kinemotion-0.11.4}/tests/test_contact_detection.py +0 -0
  68. {kinemotion-0.11.2 → kinemotion-0.11.4}/tests/test_filtering.py +0 -0
  69. {kinemotion-0.11.2 → kinemotion-0.11.4}/tests/test_kinematics.py +0 -0
  70. {kinemotion-0.11.2 → kinemotion-0.11.4}/tests/test_polyorder.py +0 -0
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  <!-- version list -->
9
9
 
10
+ ## v0.11.4 (2025-11-06)
11
+
12
+ ### Bug Fixes
13
+
14
+ - **api**: Remove countermovement_threshold from CMJVideoConfig and bulk processing
15
+ ([`66ac915`](https://github.com/feniix/kinemotion/commit/66ac915810853b6c7aeca79f07f6470ef5da4041))
16
+
17
+
18
+ ## v0.11.3 (2025-11-06)
19
+
20
+ ### Bug Fixes
21
+
22
+ - Deduplicate CLI utilities across CMJ and drop jump modules
23
+ ([`c314083`](https://github.com/feniix/kinemotion/commit/c314083dd6601071f75ded38864f7ba9a9daab3d))
24
+
25
+ - **cmj**: Remove unused countermovement_threshold parameter from process_cmj_video
26
+ ([`a8d9425`](https://github.com/feniix/kinemotion/commit/a8d9425a509b44ccf5c9e983e2d8552e9b5f8839))
27
+
28
+
10
29
  ## v0.11.2 (2025-11-06)
11
30
 
12
31
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kinemotion
3
- Version: 0.11.2
3
+ Version: 0.11.4
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kinemotion"
3
- version = "0.11.2"
3
+ version = "0.11.4"
4
4
  description = "Video-based kinematic analysis for athletic performance"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10,<3.13"
@@ -620,7 +620,6 @@ class CMJVideoConfig:
620
620
  json_output: str | None = None
621
621
  smoothing_window: int | None = None
622
622
  velocity_threshold: float | None = None
623
- countermovement_threshold: float | None = None
624
623
  min_contact_frames: int | None = None
625
624
  visibility_threshold: float | None = None
626
625
  detection_confidence: float | None = None
@@ -689,7 +688,6 @@ def process_cmj_video(
689
688
  json_output: str | None = None,
690
689
  smoothing_window: int | None = None,
691
690
  velocity_threshold: float | None = None,
692
- countermovement_threshold: float | None = None,
693
691
  min_contact_frames: int | None = None,
694
692
  visibility_threshold: float | None = None,
695
693
  detection_confidence: float | None = None,
@@ -710,7 +708,6 @@ def process_cmj_video(
710
708
  json_output: Optional path for JSON metrics output
711
709
  smoothing_window: Optional override for smoothing window
712
710
  velocity_threshold: Optional override for velocity threshold
713
- countermovement_threshold: Optional override for countermovement threshold
714
711
  min_contact_frames: Optional override for minimum contact frames
715
712
  visibility_threshold: Optional override for visibility threshold
716
713
  detection_confidence: Optional override for pose detection confidence
@@ -929,7 +926,6 @@ def _process_cmj_video_wrapper(config: CMJVideoConfig) -> CMJVideoResult:
929
926
  json_output=config.json_output,
930
927
  smoothing_window=config.smoothing_window,
931
928
  velocity_threshold=config.velocity_threshold,
932
- countermovement_threshold=config.countermovement_threshold,
933
929
  min_contact_frames=config.min_contact_frames,
934
930
  visibility_threshold=config.visibility_threshold,
935
931
  detection_confidence=config.detection_confidence,
@@ -18,8 +18,12 @@ from ..core.auto_tuning import (
18
18
  analyze_video_sample,
19
19
  auto_tune_parameters,
20
20
  )
21
+ from ..core.cli_utils import (
22
+ determine_initial_confidence,
23
+ smooth_landmark_sequence,
24
+ track_all_frames,
25
+ )
21
26
  from ..core.pose import PoseTracker
22
- from ..core.smoothing import smooth_landmarks, smooth_landmarks_advanced
23
27
  from ..core.video_io import VideoProcessor
24
28
  from .analysis import detect_cmj_phases
25
29
  from .debug_overlay import CMJDebugOverlayRenderer
@@ -295,53 +299,6 @@ def cmj_analyze( # NOSONAR(S107) - Click CLI requires individual parameters for
295
299
  sys.exit(1)
296
300
 
297
301
 
298
- def _determine_initial_confidence(
299
- quality_preset: QualityPreset,
300
- expert_params: AnalysisParameters,
301
- ) -> tuple[float, float]:
302
- """Determine initial detection and tracking confidence levels."""
303
- initial_detection_conf = 0.5
304
- initial_tracking_conf = 0.5
305
-
306
- if quality_preset == QualityPreset.FAST:
307
- initial_detection_conf = 0.3
308
- initial_tracking_conf = 0.3
309
- elif quality_preset == QualityPreset.ACCURATE:
310
- initial_detection_conf = 0.6
311
- initial_tracking_conf = 0.6
312
-
313
- # Override with expert values if provided
314
- if expert_params.detection_confidence is not None:
315
- initial_detection_conf = expert_params.detection_confidence
316
- if expert_params.tracking_confidence is not None:
317
- initial_tracking_conf = expert_params.tracking_confidence
318
-
319
- return initial_detection_conf, initial_tracking_conf
320
-
321
-
322
- def _track_all_frames(video: VideoProcessor, tracker: PoseTracker) -> tuple[list, list]:
323
- """Track pose landmarks in all video frames."""
324
- click.echo("Tracking pose landmarks...", err=True)
325
- landmarks_sequence = []
326
- frames = []
327
-
328
- bar: Any
329
- with click.progressbar(length=video.frame_count, label="Processing frames") as bar:
330
- while True:
331
- frame = video.read_frame()
332
- if frame is None:
333
- break
334
-
335
- frames.append(frame)
336
- landmarks = tracker.process_frame(frame)
337
- landmarks_sequence.append(landmarks)
338
-
339
- bar.update(1)
340
-
341
- tracker.close()
342
- return frames, landmarks_sequence
343
-
344
-
345
302
  def _apply_expert_param_overrides(
346
303
  params: AutoTunedParams, expert_params: AnalysisParameters
347
304
  ) -> AutoTunedParams:
@@ -386,34 +343,6 @@ def _print_auto_tuned_params(
386
343
  click.echo("=" * 60 + "\n", err=True)
387
344
 
388
345
 
389
- def _smooth_landmark_sequence(
390
- landmarks_sequence: list, params: AutoTunedParams
391
- ) -> list:
392
- """Apply smoothing to landmark sequence."""
393
- if params.outlier_rejection or params.bilateral_filter:
394
- if params.outlier_rejection:
395
- click.echo("Smoothing landmarks with outlier rejection...", err=True)
396
- if params.bilateral_filter:
397
- click.echo(
398
- "Using bilateral temporal filter for edge-preserving smoothing...",
399
- err=True,
400
- )
401
- return smooth_landmarks_advanced(
402
- landmarks_sequence,
403
- window_length=params.smoothing_window,
404
- polyorder=params.polyorder,
405
- use_outlier_rejection=params.outlier_rejection,
406
- use_bilateral=params.bilateral_filter,
407
- )
408
- else:
409
- click.echo("Smoothing landmarks...", err=True)
410
- return smooth_landmarks(
411
- landmarks_sequence,
412
- window_length=params.smoothing_window,
413
- polyorder=params.polyorder,
414
- )
415
-
416
-
417
346
  def _get_foot_position(frame_landmarks: dict | None, last_position: float) -> float:
418
347
  """Extract average foot position from frame landmarks."""
419
348
  if not frame_landmarks:
@@ -470,7 +399,7 @@ def _process_single(
470
399
  )
471
400
 
472
401
  # Determine confidence levels
473
- detection_conf, tracking_conf = _determine_initial_confidence(
402
+ detection_conf, tracking_conf = determine_initial_confidence(
474
403
  quality_preset, expert_params
475
404
  )
476
405
 
@@ -479,7 +408,7 @@ def _process_single(
479
408
  min_detection_confidence=detection_conf,
480
409
  min_tracking_confidence=tracking_conf,
481
410
  )
482
- frames, landmarks_sequence = _track_all_frames(video, tracker)
411
+ frames, landmarks_sequence = track_all_frames(video, tracker)
483
412
 
484
413
  if not landmarks_sequence:
485
414
  click.echo("Error: No frames processed", err=True)
@@ -505,7 +434,7 @@ def _process_single(
505
434
  )
506
435
 
507
436
  # Apply smoothing
508
- smoothed_landmarks = _smooth_landmark_sequence(landmarks_sequence, params)
437
+ smoothed_landmarks = smooth_landmark_sequence(landmarks_sequence, params)
509
438
 
510
439
  # Extract foot positions
511
440
  vertical_positions, tracking_method = _extract_positions_from_landmarks(
@@ -0,0 +1,113 @@
1
+ """Shared CLI utilities for drop jump and CMJ analysis."""
2
+
3
+ from typing import Any, Protocol
4
+
5
+ import click
6
+
7
+ from .auto_tuning import AutoTunedParams, QualityPreset
8
+ from .pose import PoseTracker
9
+ from .smoothing import smooth_landmarks, smooth_landmarks_advanced
10
+ from .video_io import VideoProcessor
11
+
12
+
13
+ class ExpertParameters(Protocol):
14
+ """Protocol for expert parameter overrides."""
15
+
16
+ detection_confidence: float | None
17
+ tracking_confidence: float | None
18
+
19
+
20
+ def determine_initial_confidence(
21
+ quality_preset: QualityPreset,
22
+ expert_params: ExpertParameters,
23
+ ) -> tuple[float, float]:
24
+ """Determine initial detection and tracking confidence levels.
25
+
26
+ Args:
27
+ quality_preset: Quality preset enum
28
+ expert_params: Expert parameter overrides
29
+
30
+ Returns:
31
+ Tuple of (detection_confidence, tracking_confidence)
32
+ """
33
+ initial_detection_conf = 0.5
34
+ initial_tracking_conf = 0.5
35
+
36
+ if quality_preset == QualityPreset.FAST:
37
+ initial_detection_conf = 0.3
38
+ initial_tracking_conf = 0.3
39
+ elif quality_preset == QualityPreset.ACCURATE:
40
+ initial_detection_conf = 0.6
41
+ initial_tracking_conf = 0.6
42
+
43
+ # Override with expert values if provided
44
+ if expert_params.detection_confidence is not None:
45
+ initial_detection_conf = expert_params.detection_confidence
46
+ if expert_params.tracking_confidence is not None:
47
+ initial_tracking_conf = expert_params.tracking_confidence
48
+
49
+ return initial_detection_conf, initial_tracking_conf
50
+
51
+
52
+ def track_all_frames(video: VideoProcessor, tracker: PoseTracker) -> tuple[list, list]:
53
+ """Track pose landmarks in all video frames.
54
+
55
+ Args:
56
+ video: Video processor
57
+ tracker: Pose tracker
58
+
59
+ Returns:
60
+ Tuple of (frames, landmarks_sequence)
61
+ """
62
+ click.echo("Tracking pose landmarks...", err=True)
63
+ landmarks_sequence = []
64
+ frames = []
65
+
66
+ bar: Any
67
+ with click.progressbar(length=video.frame_count, label="Processing frames") as bar:
68
+ while True:
69
+ frame = video.read_frame()
70
+ if frame is None:
71
+ break
72
+
73
+ frames.append(frame)
74
+ landmarks = tracker.process_frame(frame)
75
+ landmarks_sequence.append(landmarks)
76
+ bar.update(1)
77
+
78
+ tracker.close()
79
+ return frames, landmarks_sequence
80
+
81
+
82
+ def smooth_landmark_sequence(landmarks_sequence: list, params: AutoTunedParams) -> list:
83
+ """Apply smoothing to landmark sequence.
84
+
85
+ Args:
86
+ landmarks_sequence: Raw landmark sequence
87
+ params: Auto-tuned parameters
88
+
89
+ Returns:
90
+ Smoothed landmark sequence
91
+ """
92
+ if params.outlier_rejection or params.bilateral_filter:
93
+ if params.outlier_rejection:
94
+ click.echo("Smoothing landmarks with outlier rejection...", err=True)
95
+ if params.bilateral_filter:
96
+ click.echo(
97
+ "Using bilateral temporal filter for edge-preserving smoothing...",
98
+ err=True,
99
+ )
100
+ return smooth_landmarks_advanced(
101
+ landmarks_sequence,
102
+ window_length=params.smoothing_window,
103
+ polyorder=params.polyorder,
104
+ use_outlier_rejection=params.outlier_rejection,
105
+ use_bilateral=params.bilateral_filter,
106
+ )
107
+ else:
108
+ click.echo("Smoothing landmarks...", err=True)
109
+ return smooth_landmarks(
110
+ landmarks_sequence,
111
+ window_length=params.smoothing_window,
112
+ polyorder=params.polyorder,
113
+ )
@@ -21,8 +21,12 @@ from ..core.auto_tuning import (
21
21
  analyze_video_sample,
22
22
  auto_tune_parameters,
23
23
  )
24
+ from ..core.cli_utils import (
25
+ determine_initial_confidence,
26
+ smooth_landmark_sequence,
27
+ track_all_frames,
28
+ )
24
29
  from ..core.pose import PoseTracker
25
- from ..core.smoothing import smooth_landmarks, smooth_landmarks_advanced
26
30
  from ..core.video_io import VideoProcessor
27
31
  from .analysis import (
28
32
  ContactState,
@@ -256,69 +260,6 @@ def dropjump_analyze( # NOSONAR(S107) - Click CLI requires individual parameter
256
260
  )
257
261
 
258
262
 
259
- def _determine_initial_confidence(
260
- quality_preset: QualityPreset,
261
- expert_params: AnalysisParameters,
262
- ) -> tuple[float, float]:
263
- """Determine initial detection and tracking confidence levels.
264
-
265
- Args:
266
- quality_preset: Quality preset enum
267
- expert_params: Expert parameter overrides
268
-
269
- Returns:
270
- Tuple of (detection_confidence, tracking_confidence)
271
- """
272
- initial_detection_conf = 0.5
273
- initial_tracking_conf = 0.5
274
-
275
- if quality_preset == QualityPreset.FAST:
276
- initial_detection_conf = 0.3
277
- initial_tracking_conf = 0.3
278
- elif quality_preset == QualityPreset.ACCURATE:
279
- initial_detection_conf = 0.6
280
- initial_tracking_conf = 0.6
281
-
282
- # Override with expert values if provided
283
- if expert_params.detection_confidence is not None:
284
- initial_detection_conf = expert_params.detection_confidence
285
- if expert_params.tracking_confidence is not None:
286
- initial_tracking_conf = expert_params.tracking_confidence
287
-
288
- return initial_detection_conf, initial_tracking_conf
289
-
290
-
291
- def _track_all_frames(video: VideoProcessor, tracker: PoseTracker) -> tuple[list, list]:
292
- """Track pose landmarks in all video frames.
293
-
294
- Args:
295
- video: Video processor
296
- tracker: Pose tracker
297
-
298
- Returns:
299
- Tuple of (frames, landmarks_sequence)
300
- """
301
- click.echo("Tracking pose landmarks...", err=True)
302
- landmarks_sequence = []
303
- frames = []
304
-
305
- bar: Any
306
- with click.progressbar(length=video.frame_count, label="Processing frames") as bar:
307
- while True:
308
- frame = video.read_frame()
309
- if frame is None:
310
- break
311
-
312
- frames.append(frame)
313
- landmarks = tracker.process_frame(frame)
314
- landmarks_sequence.append(landmarks)
315
-
316
- bar.update(1)
317
-
318
- tracker.close()
319
- return frames, landmarks_sequence
320
-
321
-
322
263
  def _apply_expert_param_overrides(
323
264
  params: AutoTunedParams, expert_params: AnalysisParameters
324
265
  ) -> AutoTunedParams:
@@ -380,42 +321,6 @@ def _print_auto_tuned_params(
380
321
  click.echo("=" * 60 + "\n", err=True)
381
322
 
382
323
 
383
- def _smooth_landmark_sequence(
384
- landmarks_sequence: list, params: AutoTunedParams
385
- ) -> list:
386
- """Apply smoothing to landmark sequence.
387
-
388
- Args:
389
- landmarks_sequence: Raw landmark sequence
390
- params: Auto-tuned parameters
391
-
392
- Returns:
393
- Smoothed landmarks
394
- """
395
- if params.outlier_rejection or params.bilateral_filter:
396
- if params.outlier_rejection:
397
- click.echo("Smoothing landmarks with outlier rejection...", err=True)
398
- if params.bilateral_filter:
399
- click.echo(
400
- "Using bilateral temporal filter for edge-preserving smoothing...",
401
- err=True,
402
- )
403
- return smooth_landmarks_advanced(
404
- landmarks_sequence,
405
- window_length=params.smoothing_window,
406
- polyorder=params.polyorder,
407
- use_outlier_rejection=params.outlier_rejection,
408
- use_bilateral=params.bilateral_filter,
409
- )
410
- else:
411
- click.echo("Smoothing landmarks...", err=True)
412
- return smooth_landmarks(
413
- landmarks_sequence,
414
- window_length=params.smoothing_window,
415
- polyorder=params.polyorder,
416
- )
417
-
418
-
419
324
  def _extract_positions_and_visibilities(
420
325
  smoothed_landmarks: list,
421
326
  ) -> tuple[np.ndarray, np.ndarray]:
@@ -533,7 +438,7 @@ def _process_single(
533
438
  )
534
439
 
535
440
  # Determine confidence levels
536
- detection_conf, tracking_conf = _determine_initial_confidence(
441
+ detection_conf, tracking_conf = determine_initial_confidence(
537
442
  quality_preset, expert_params
538
443
  )
539
444
 
@@ -542,7 +447,7 @@ def _process_single(
542
447
  min_detection_confidence=detection_conf,
543
448
  min_tracking_confidence=tracking_conf,
544
449
  )
545
- frames, landmarks_sequence = _track_all_frames(video, tracker)
450
+ frames, landmarks_sequence = track_all_frames(video, tracker)
546
451
 
547
452
  if not landmarks_sequence:
548
453
  click.echo("Error: No frames processed", err=True)
@@ -560,7 +465,7 @@ def _process_single(
560
465
  _print_auto_tuned_params(video, characteristics, quality_preset, params)
561
466
 
562
467
  # Apply smoothing
563
- smoothed_landmarks = _smooth_landmark_sequence(landmarks_sequence, params)
468
+ smoothed_landmarks = smooth_landmark_sequence(landmarks_sequence, params)
564
469
 
565
470
  # Extract positions
566
471
  vertical_positions, visibilities = _extract_positions_and_visibilities(
@@ -603,7 +603,7 @@ wheels = [
603
603
 
604
604
  [[package]]
605
605
  name = "kinemotion"
606
- version = "0.11.2"
606
+ version = "0.11.4"
607
607
  source = { editable = "." }
608
608
  dependencies = [
609
609
  { name = "click" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes