Spaces:
Sleeping
Sleeping
Create utils.py
Browse files
utils.py
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import math
|
2 |
+
|
3 |
+
def euclidean_distance(p1, p2):
|
4 |
+
"""
|
5 |
+
Returns the Euclidean distance between two (x, y) points.
|
6 |
+
"""
|
7 |
+
return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
|
8 |
+
|
9 |
+
def estimate_ball_speed(ball_positions, fps=25, scale=0.01):
|
10 |
+
"""
|
11 |
+
Estimates average ball speed in meters/second.
|
12 |
+
|
13 |
+
Args:
|
14 |
+
ball_positions: List of (frame_idx, x, y)
|
15 |
+
fps: Frame rate of video
|
16 |
+
scale: Pixel-to-meter conversion (assumed or calibrated)
|
17 |
+
|
18 |
+
Returns:
|
19 |
+
float: estimated speed (m/s)
|
20 |
+
"""
|
21 |
+
if len(ball_positions) < 2:
|
22 |
+
return 0.0
|
23 |
+
|
24 |
+
distances = []
|
25 |
+
for i in range(1, len(ball_positions)):
|
26 |
+
_, x1, y1 = ball_positions[i - 1]
|
27 |
+
_, x2, y2 = ball_positions[i]
|
28 |
+
dist_px = euclidean_distance((x1, y1), (x2, y2))
|
29 |
+
distances.append(dist_px)
|
30 |
+
|
31 |
+
avg_px_per_frame = sum(distances) / len(distances)
|
32 |
+
speed_m_per_s = avg_px_per_frame * scale * fps
|
33 |
+
return round(speed_m_per_s, 2)
|
34 |
+
|
35 |
+
def frame_to_time(frame_idx, fps):
|
36 |
+
"""
|
37 |
+
Converts frame index to timestamp (seconds).
|
38 |
+
"""
|
39 |
+
return round(frame_idx / fps, 2)
|
40 |
+
|
41 |
+
def format_impact_info(impact_frame, impact_type, fps):
|
42 |
+
"""
|
43 |
+
Creates a descriptive impact summary.
|
44 |
+
"""
|
45 |
+
time_sec = frame_to_time(impact_frame, fps)
|
46 |
+
return f"Impact at {time_sec}s on {impact_type.upper()}"
|
47 |
+
|
48 |
+
def log(message):
|
49 |
+
"""
|
50 |
+
Simple print logger with prefix.
|
51 |
+
"""
|
52 |
+
print(f"[LBW-DRS] {message}")
|