Mirko Trasciatti commited on
Commit
62b40d2
·
1 Parent(s): 778b9c7

Use adaptive speed threshold and area fallback for kick detection

Browse files
Files changed (1) hide show
  1. app.py +13 -8
app.py CHANGED
@@ -575,11 +575,14 @@ def _detect_kick_frame(state: AppState, target_obj_id: int) -> int | None:
575
  frames = sorted(smoothed.keys())
576
  speed_series = [speeds.get(f, 0.0) for f in frames]
577
 
578
- baseline_window = min(5, len(frames) // 3 or 1)
579
  baseline_speeds = speed_series[:baseline_window]
580
  baseline_speed = statistics.median(baseline_speeds) if baseline_speeds else 0.0
581
-
582
- speed_threshold = baseline_speed + 80.0 # pixels/second
 
 
 
583
  sustain_frames = 3
584
  holdout_frames = 8
585
  return_distance = 12.0
@@ -598,14 +601,14 @@ def _detect_kick_frame(state: AppState, target_obj_id: int) -> int | None:
598
  for j in range(1, sustain_frames + 1):
599
  if idx + j >= len(frames):
600
  break
601
- if speed_series[idx + j] < speed_threshold * 0.8:
602
  sustain_ok = False
603
  break
604
  if not sustain_ok:
605
  continue
606
 
607
- area_pass = True
608
  current_area = areas_dict.get(frame)
 
609
  if current_area:
610
  prev_areas = [
611
  areas_dict.get(f)
@@ -614,9 +617,11 @@ def _detect_kick_frame(state: AppState, target_obj_id: int) -> int | None:
614
  ]
615
  if prev_areas:
616
  median_prev = statistics.median(prev_areas)
617
- if median_prev > 0 and current_area / median_prev > area_drop_ratio:
618
- area_pass = False
619
- if not area_pass:
 
 
620
  continue
621
 
622
  moved_far = True
 
575
  frames = sorted(smoothed.keys())
576
  speed_series = [speeds.get(f, 0.0) for f in frames]
577
 
578
+ baseline_window = min(10, len(frames) // 3 or 1)
579
  baseline_speeds = speed_series[:baseline_window]
580
  baseline_speed = statistics.median(baseline_speeds) if baseline_speeds else 0.0
581
+ speed_std = statistics.pstdev(baseline_speeds) if len(baseline_speeds) > 1 else 0.0
582
+ base_threshold = baseline_speed + 4.0 * speed_std
583
+ if base_threshold < baseline_speed * 3.0:
584
+ base_threshold = baseline_speed * 3.0
585
+ speed_threshold = max(base_threshold, 15.0)
586
  sustain_frames = 3
587
  holdout_frames = 8
588
  return_distance = 12.0
 
601
  for j in range(1, sustain_frames + 1):
602
  if idx + j >= len(frames):
603
  break
604
+ if speed_series[idx + j] < speed_threshold * 0.7:
605
  sustain_ok = False
606
  break
607
  if not sustain_ok:
608
  continue
609
 
 
610
  current_area = areas_dict.get(frame)
611
+ area_pass = True
612
  if current_area:
613
  prev_areas = [
614
  areas_dict.get(f)
 
617
  ]
618
  if prev_areas:
619
  median_prev = statistics.median(prev_areas)
620
+ if median_prev > 0:
621
+ ratio = current_area / median_prev
622
+ if ratio > area_drop_ratio:
623
+ area_pass = False
624
+ if not area_pass and speed < speed_threshold * 1.2:
625
  continue
626
 
627
  moved_far = True