chandra7799 commited on
Commit
501a48f
·
verified ·
1 Parent(s): fadcfa4

Update pages/live_match.py

Browse files
Files changed (1) hide show
  1. pages/live_match.py +112 -64
pages/live_match.py CHANGED
@@ -1,74 +1,122 @@
1
- import gradio as gr
2
- import cv2
3
- import time
4
- import re
5
- from gully_drs_core.model_utils import load_yolov5_model, detect_objects
6
- from gully_drs_core.ball_detection import track_ball_and_estimate_speed, detect_lbw
7
- from gully_drs_core.replay_utils import generate_replay
8
-
9
- def validate_url(url):
10
- """Validate live video URL."""
11
  try:
12
- if not url:
13
- return False, "No URL provided."
14
- if not re.match(r'^https?://[a-zA-Z0-9:/._-]*$|^rtsp://[a-zA-Z0-9:/._-]*$', url):
15
- return False, "Invalid URL format. Use HTTP/HTTPS or RTSP URLs."
16
- return True, ""
17
- except Exception as e:
18
- return False, f"Error validating URL: {str(e)}"
19
-
20
- def process_live_video(live_url, state, drs_button):
21
- """Process live video stream with DRS LBW functionality."""
22
- try:
23
- is_valid, error_msg = validate_url(live_url)
24
  if not is_valid:
25
- yield None, error_msg, None, state
26
- return
27
-
28
- cap = cv2.VideoCapture(live_url)
29
  if not cap.isOpened():
30
- yield None, "Unable to open live stream.", None, state
31
- return
32
-
33
- model = load_yolov5_model()
34
  frame_rate = cap.get(cv2.CAP_PROP_FPS) or 30
35
- frames, detections, speeds, lbw_verdicts = [], [], [], []
 
 
 
 
 
 
36
  ball_positions = state.get("ball_positions", [])
37
- start_time = state.get("start_time", None)
38
-
39
- if drs_button:
40
- state["drs_triggered"] = True
41
- state["start_time"] = time.time()
42
- start_time = state["start_time"]
43
-
44
- while cap.isOpened():
45
  ret, frame = cap.read()
46
  if not ret:
47
  break
48
-
49
- if start_time and time.time() - start_time > 5: # Trim to 5 seconds
50
- break
51
-
52
- frames.append(frame)
53
- results = detect_objects(frame, model)
54
- detections.append(results.xyxy[0])
55
- frame, speed, pos = track_ball_and_estimate_speed(frame, results.xyxy[0], frame_rate)
56
- speeds.append(speed)
57
- if pos:
58
- ball_positions.append(pos)
59
- lbw_verdict, ball_positions = detect_lbw(results.xyxy[0], frame.shape, ball_positions)
60
- lbw_verdicts.append(lbw_verdict)
61
- state["ball_positions"] = ball_positions
62
-
63
- yield frame, None, None, state
64
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  cap.release()
66
-
67
- if state.get("drs_triggered", False):
68
- replay_path = generate_replay(frames, detections, speeds, lbw_verdicts[-1])
69
- yield replay_path, lbw_verdicts[-1], f"{speeds[-1]:.2f} km/h", state
70
- else:
71
- yield None, "Press DRS LBW to analyze.", None, state
72
-
 
 
 
 
 
 
 
73
  except Exception as e:
74
- yield None, f"Error: {str(e)}", None, state
 
1
+ def process_live_video(url, state, button_click):
2
+ """
3
+ Process a live video stream for LBW decision and ball speed.
4
+ url: String URL of the live video stream (RTSP/HTTP).
5
+ state: Gradio state for maintaining context.
6
+ button_click: Button state (triggered on DRS LBW click).
7
+ """
 
 
 
8
  try:
9
+ # Validate URL
10
+ is_valid, message = validate_url(url)
 
 
 
 
 
 
 
 
 
 
11
  if not is_valid:
12
+ return None, message, "N/A", state
13
+
14
+ # Open the live stream
15
+ cap = cv2.VideoCapture(url)
16
  if not cap.isOpened():
17
+ return None, "Error: Could not open video stream", "N/A", state
18
+
19
+ # Get video properties
 
20
  frame_rate = cap.get(cv2.CAP_PROP_FPS) or 30
21
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
22
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
23
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
24
+ slow_motion_factor = 4 # Maintain slow motion
25
+ out = cv2.VideoWriter("processed_video.mp4", fourcc, frame_rate / slow_motion_factor, (width, height))
26
+
27
+ # Initialize variables
28
  ball_positions = state.get("ball_positions", [])
29
+ ball_speed = 0.0
30
+ lbw_detected = False
31
+ frame_count = 0
32
+ prev_position = None
33
+ start_time = time.time() if button_click else state.get("start_time", None)
34
+ drs_review = "DRS Review: N/A"
35
+
36
+ while cap.isOpened() and (not button_click or time.time() - start_time < 5):
37
  ret, frame = cap.read()
38
  if not ret:
39
  break
40
+
41
+ # Refined ball detection (tighter HSV, size, aspect ratio, and height filters)
42
+ hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
43
+ lower_red = np.array([0, 150, 120]) # Tighter red range to exclude shoes
44
+ upper_red = np.array([10, 255, 255])
45
+ mask = cv2.inRange(hsv, lower_red, upper_red)
46
+ contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
47
+ ball_detected = False
48
+ if contours:
49
+ largest_contour = max(contours, key=cv2.contourArea)
50
+ x, y, w, h = cv2.boundingRect(largest_contour)
51
+ aspect_ratio = float(w) / h
52
+ if 20 < cv2.contourArea(largest_contour) < 500 and 0.5 < aspect_ratio < 1.5 and y < height - 200: # Exclude elongated shoes
53
+ ball_position = (x + w // 2, y + h // 2)
54
+ if not prev_position and frame_count < 10: # Initial position
55
+ prev_position = ball_position
56
+ if prev_position and abs(ball_position[1] - prev_position[1]) > 2: # Motion filter
57
+ ball_positions.append(ball_position)
58
+ cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 4) # Thicker green
59
+ cv2.putText(frame, "Ball", (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
60
+ ball_detected = True
61
+
62
+ # Refined wickets detection
63
+ stump_region = frame[height - 250:height, width // 2 - 120:width // 2 + 120]
64
+ gray_stump = cv2.cvtColor(stump_region, cv2.COLOR_BGR2GRAY)
65
+ _, stump_mask = cv2.threshold(gray_stump, 200, 255, cv2.THRESH_BINARY)
66
+ if np.sum(stump_mask) > 1200:
67
+ cv2.rectangle(frame, (width // 2 - 120, height - 250), (width // 2 + 120, height - 50), (0, 0, 255), 3)
68
+ cv2.putText(frame, "Wickets", (width // 2 - 120, height - 260), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
69
+
70
+ # Refined batsman leg pads detection
71
+ leg_pads_region = frame[height // 2 + 50:height, width // 3:2 * width // 3]
72
+ gray_leg_pads = cv2.cvtColor(leg_pads_region, cv2.COLOR_BGR2GRAY)
73
+ _, leg_pads_mask = cv2.threshold(gray_leg_pads, 90, 255, cv2.THRESH_BINARY_INV)
74
+ if np.sum(leg_pads_mask) > 4000:
75
+ cv2.rectangle(frame, (width // 3, height // 2 + 50), (2 * width // 3, height), (255, 0, 0), 3)
76
+ cv2.putText(frame, "Leg Pads", (width // 3, height // 2 + 40), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
77
+
78
+ # Ball speed estimation
79
+ if ball_detected and prev_position and frame_count > 1:
80
+ dx = ball_position[0] - prev_position[0]
81
+ dy = ball_position[1] - prev_position[1]
82
+ distance = np.sqrt(dx**2 + dy**2)
83
+ time_diff = 1 / frame_rate
84
+ ball_speed = min(200, max(20, distance / time_diff * 0.012))
85
+
86
+ # Enhanced LBW detection
87
+ if ball_detected and len(ball_positions) > 5:
88
+ last_five = ball_positions[-5:]
89
+ impact_wickets = any(width // 2 - 120 < pos[0] < width // 2 + 120 and height - 250 < pos[1] < height - 50 for pos in last_five)
90
+ impact_pads = any(width // 3 < pos[0] < 2 * width // 3 and height // 2 + 50 < pos[1] < height for pos in last_five)
91
+ if impact_wickets or (impact_pads and ball_speed > 40):
92
+ lbw_detected = True
93
+ drs_review = f"DRS Review: Ball impacting {'wickets' if impact_wickets else 'leg pads'} at {ball_position[0]}px, {ball_position[1]}px. Speed: {ball_speed:.2f} km/h. Decision: Out."
94
+ cv2.putText(frame, drs_review[:50], (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255, 255, 255), 1)
95
+ else:
96
+ drs_review = "DRS Review: No LBW. Ball missed wickets and pads."
97
+
98
+ # Write frame to slow-motion video
99
+ if button_click and start_time:
100
+ for _ in range(slow_motion_factor):
101
+ out.write(frame)
102
+
103
+ prev_position = ball_position
104
+ frame_count += 1
105
+
106
  cap.release()
107
+ out.release()
108
+
109
+ # Check if any ball was detected
110
+ if not any(ball_positions):
111
+ return "processed_video.mp4", "No red ball detected", "N/A", state
112
+
113
+ lbw_decision = "Out" if lbw_detected else "Not Out"
114
+ lbw_decision = f"{lbw_decision}\n{drs_review}"
115
+ ball_speed_str = f"{ball_speed:.2f} km/h" if ball_speed > 0 else "N/A"
116
+
117
+ state["ball_positions"] = ball_positions
118
+ state["start_time"] = start_time
119
+
120
+ return "processed_video.mp4", lbw_decision, ball_speed_str, state
121
  except Exception as e:
122
+ return None, f"Error processing video: {str(e)}. Ensure video is MP4 with H.264 codec and contains a visible red ball.", "N/A", state