dschandra commited on
Commit
de182d4
·
verified ·
1 Parent(s): f04b386

Upload 8 files

Browse files
Files changed (8) hide show
  1. app.py +35 -0
  2. ball_tracker.py +21 -0
  3. gradio_app.py +53 -0
  4. lbw_engine.py +17 -0
  5. overlay_display.py +69 -0
  6. requirements.txt +0 -0
  7. test_app.py +2 -0
  8. trajectory.py +22 -0
app.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ from ball_tracker import detect_ball
3
+ from trajectory import predict_trajectory
4
+ from lbw_engine import evaluate_lbw
5
+ from overlay_display import draw_overlay
6
+
7
+ cap = cv2.VideoCapture(0)
8
+ ball_path = []
9
+
10
+ while True:
11
+ ret, frame = cap.read()
12
+ if not ret:
13
+ break
14
+
15
+ ball = detect_ball(frame)
16
+ if ball:
17
+ ball_path.append(ball)
18
+
19
+ if len(ball_path) > 5:
20
+ a, b, c = predict_trajectory(ball_path)
21
+ trajectory_func = lambda x: a * x**2 + b * x + c
22
+
23
+ pitch_x = ball_path[0][0]
24
+ impact_x = ball_path[-1][0]
25
+ wicket_x = int((impact_x + 100) / 2)
26
+
27
+ verdict, pitch, impact, wickets = evaluate_lbw(pitch_x, impact_x, wicket_x, ball_path)
28
+ frame = draw_overlay(frame, ball_path, trajectory_func, verdict, (pitch, impact, wickets))
29
+
30
+ cv2.imshow("Gully Cricket DRS", frame)
31
+ if cv2.waitKey(1) == ord('q'):
32
+ break
33
+
34
+ cap.release()
35
+ cv2.destroyAllWindows()
ball_tracker.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+
4
+ def detect_ball(frame):
5
+ hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
6
+ lower_red1 = np.array([0, 100, 100])
7
+ upper_red1 = np.array([10, 255, 255])
8
+ lower_red2 = np.array([160, 100, 100])
9
+ upper_red2 = np.array([180, 255, 255])
10
+
11
+ mask1 = cv2.inRange(hsv, lower_red1, upper_red1)
12
+ mask2 = cv2.inRange(hsv, lower_red2, upper_red2)
13
+ mask = mask1 | mask2
14
+
15
+ contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
16
+ if contours:
17
+ largest = max(contours, key=cv2.contourArea)
18
+ (x, y), radius = cv2.minEnclosingCircle(largest)
19
+ return (int(x), int(y))
20
+ return None
21
+
gradio_app.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import cv2
3
+ import numpy as np
4
+ from ball_tracker import detect_ball
5
+ from trajectory import predict_trajectory
6
+ from lbw_engine import evaluate_lbw
7
+ from overlay_display import draw_overlay
8
+ import tempfile
9
+
10
+ def process_video(video_file):
11
+ cap = cv2.VideoCapture(video_file)
12
+ ball_path = []
13
+ output_frames = []
14
+
15
+ while cap.isOpened():
16
+ ret, frame = cap.read()
17
+ if not ret:
18
+ break
19
+
20
+ ball = detect_ball(frame)
21
+ if ball:
22
+ ball_path.append(ball)
23
+
24
+ if len(ball_path) > 5:
25
+ try:
26
+ a, b, c = predict_trajectory(ball_path)
27
+ trajectory_func = lambda x: a * x**2 + b * x + c
28
+ pitch_x = ball_path[0][0]
29
+ impact_x = ball_path[-1][0]
30
+ wicket_x = int((impact_x + 100) / 2)
31
+ frame_width = frame.shape[1]
32
+ verdict, pitch, impact, wickets = evaluate_lbw(pitch_x, impact_x, wicket_x, ball_path, frame_width)
33
+ frame = draw_overlay(frame, ball_path, trajectory_func, verdict, (pitch, impact, wickets))
34
+ except Exception as e:
35
+ print("Prediction error:", e)
36
+
37
+ output_frames.append(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
38
+
39
+ cap.release()
40
+
41
+ return output_frames[-1] if output_frames else None
42
+
43
+
44
+ demo = gr.Interface(
45
+ fn=process_video,
46
+ inputs=gr.Video(label="Upload a Cricket Delivery Video"),
47
+ outputs=gr.Image(label="Decision Frame with Overlay"),
48
+ title="🏏 Gully Cricket DRS - LBW Analysis"
49
+ )
50
+
51
+ if __name__ == "__main__":
52
+ demo.launch(inbrowser=True, share=False)
53
+
lbw_engine.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def evaluate_lbw(pitch_x, impact_x, wicket_x, predicted_path, frame_width):
2
+ # Use frame-relative zones instead of fixed pixel values
3
+ leg_boundary = int(frame_width * 0.33)
4
+ off_boundary = int(frame_width * 0.66)
5
+
6
+ # Determine zones
7
+ pitch_zone = "In Line" if leg_boundary < pitch_x < off_boundary else "Outside Leg"
8
+ impact_zone = "In Line" if leg_boundary < impact_x < off_boundary else "Outside Off"
9
+ hitting_wickets = leg_boundary < wicket_x < off_boundary
10
+
11
+ if pitch_zone == "Outside Leg":
12
+ return "Not Out", pitch_zone, impact_zone, "Missing"
13
+ if impact_zone != "In Line":
14
+ return "Not Out", pitch_zone, impact_zone, "Missing"
15
+ if hitting_wickets:
16
+ return "Out", pitch_zone, impact_zone, "Hitting"
17
+ return "Not Out", pitch_zone, impact_zone, "Missing"
overlay_display.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+
3
+ def draw_overlay(frame, ball_points, trajectory_func, verdict, labels):
4
+ height, width = frame.shape[:2]
5
+
6
+ # 1. Draw smooth RED arc (trajectory)
7
+ draw_trajectory_arc(frame, trajectory_func, ball_points[0][0], ball_points[-1][0])
8
+
9
+ # 2. Draw BLUE prediction line from impact point forward
10
+ if len(ball_points) > 1:
11
+ draw_prediction_line(frame, ball_points[-1], trajectory_func)
12
+
13
+ # 3. Draw YELLOW stumps (centered)
14
+ draw_stumps(frame, width // 2)
15
+
16
+ # 4. Display Decision and Details
17
+ text_color = (0, 255, 0) if verdict == "Out" else (0, 255, 255)
18
+ cv2.putText(frame, f"Decision: {verdict}", (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1.0, text_color, 3)
19
+ cv2.putText(frame, f"Pitching: {labels[0]}", (20, 75), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 0), 2)
20
+ cv2.putText(frame, f"Impact: {labels[1]}", (20, 105), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 0), 2)
21
+ cv2.putText(frame, f"Wickets: {labels[2]}", (20, 135), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 0), 2)
22
+
23
+ return frame
24
+
25
+
26
+ # ============================
27
+ # 📦 Helper Drawing Functions
28
+ # ============================
29
+
30
+ def draw_trajectory_arc(frame, trajectory_func, start_x, end_x, step=5, color=(0, 0, 255)):
31
+ height, width = frame.shape[:2]
32
+ for x in range(start_x, min(end_x, width - step), step):
33
+ try:
34
+ y1 = int(trajectory_func(x))
35
+ y2 = int(trajectory_func(x + step))
36
+ if 0 <= y1 < height and 0 <= y2 < height:
37
+ cv2.line(frame, (x, y1), (x + step, y2), color, 2)
38
+ except:
39
+ continue
40
+
41
+ def draw_prediction_line(frame, start_point, trajectory_func, distance=100, color=(255, 0, 0)):
42
+ x1 = start_point[0]
43
+ x2 = x1 + distance
44
+ try:
45
+ y2 = int(trajectory_func(x2))
46
+ height, width = frame.shape[:2]
47
+ if 0 <= y2 < height and x2 < width:
48
+ cv2.line(frame, start_point, (x2, y2), color, 2)
49
+ except:
50
+ pass
51
+
52
+ def draw_stumps(frame, center_x, color=(0, 255, 255)):
53
+ height = frame.shape[0]
54
+ stump_top = int(height * 0.55)
55
+ stump_bottom = int(height * 0.85)
56
+ for dx in [-10, 0, 10]:
57
+ cv2.line(frame, (center_x + dx, stump_top), (center_x + dx, stump_bottom), color, 2)
58
+
59
+ def draw_ball_path(frame, ball_path, color=(0, 255, 0)):
60
+ for i in range(1, len(ball_path)):
61
+ cv2.line(frame, ball_path[i - 1], ball_path[i], color, thickness=2)
62
+
63
+ def draw_ball(frame, position, radius=5, color=(0, 0, 255)):
64
+ cv2.circle(frame, position, radius, color, -1)
65
+
66
+ def draw_pitch_impact_wickets(frame, pitch, impact, wickets):
67
+ cv2.putText(frame, f"Pitch: {pitch}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 0), 2)
68
+ cv2.putText(frame, f"Impact: {impact}", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 0), 2)
69
+ cv2.putText(frame, f"Wickets: {wickets}", (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 0), 2)
requirements.txt ADDED
Binary file (1.85 kB). View file
 
test_app.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import streamlit as st
2
+ st.title("✅ Streamlit is working properly")
trajectory.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from scipy.optimize import curve_fit
3
+
4
+ def predict_trajectory(points):
5
+ if len(points) < 5:
6
+ raise ValueError("Not enough data points for trajectory prediction.")
7
+
8
+ points = np.array(points)
9
+ x = points[:, 0]
10
+ y = points[:, 1]
11
+
12
+ def poly2(x, a, b, c):
13
+ return a * x**2 + b * x + c
14
+
15
+ try:
16
+ params, _ = curve_fit(poly2, x, y)
17
+ except Exception as e:
18
+ print(f"Curve fitting failed: {e}")
19
+ raise e
20
+
21
+ return params
22
+