File size: 1,956 Bytes
3227154
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import numpy as np

def predict_trajectory(detection_data, pitch_height=720, stump_zone=(280, 360)):
    """
    Uses polynomial regression to predict post-impact ball trajectory.
    
    Args:
        detection_data: output from `detect_lbw_event`
        pitch_height: total frame height (in pixels) to simulate stumps
        stump_zone: x-coordinate range for stumps (min_x, max_x)

    Returns:
        dict with:
            - trajectory_points: [(x, y), ...] actual + predicted
            - decision: "OUT" or "NOT OUT"
    """
    ball_positions = detection_data["ball_positions"]
    impact_frame = detection_data["impact_frame"]

    if not ball_positions or impact_frame == -1:
        return {
            "trajectory_points": [],
            "decision": "NOT ENOUGH DATA"
        }

    # Extract coordinates pre-impact
    xs = []
    ys = []
    for idx, x, y in ball_positions:
        if idx <= impact_frame:
            xs.append(x)
            ys.append(y)

    if len(xs) < 5:
        return {
            "trajectory_points": [],
            "decision": "NOT ENOUGH POINTS"
        }

    # Fit polynomial regression (degree 2 for parabolic path)
    coeffs = np.polyfit(xs, ys, deg=2)
    poly = np.poly1d(coeffs)

    # Predict future trajectory
    last_x = xs[-1]
    future_xs = list(range(last_x, last_x + 60, 5))  # simulate 60px ahead
    future_ys = [int(poly(x)) for x in future_xs]

    trajectory_points = list(zip(xs, ys)) + list(zip(future_xs, future_ys))

    # OUT logic: predicted y crosses stump plane and x within stump zone
    for x, y in zip(future_xs, future_ys):
        if y >= pitch_height - 150:  # near stump base
            if stump_zone[0] <= x <= stump_zone[1]:
                return {
                    "trajectory_points": trajectory_points,
                    "decision": "OUT"
                }

    return {
        "trajectory_points": trajectory_points,
        "decision": "NOT OUT"
    }