import cv2 import numpy as np import gradio as gr import tempfile from pathlib import Path from cvzone.ColorModule import ColorFinder from batsman import batsman_detect from ball_detect import ball_detect # --------------------------------------------------- # Static detection parameters (tune these if needed) # --------------------------------------------------- mycolorFinder = ColorFinder(False) # HSV range for ball – tune for your footage hsvVals = { "hmin": 10, "smin": 44, "vmin": 192, "hmax": 125, "smax": 114, "vmax": 255, } # RGB range & Canny thresholds for batsman – replace with tuned values tuned_rgb_lower = np.array([112, 0, 181]) tuned_rgb_upper = np.array([255, 255, 255]) tuned_canny_threshold1 = 100 tuned_canny_threshold2 = 200 # --------------------------------------------------- # Helper to classify each frame event # --------------------------------------------------- def ball_pitch_pad(x, x_prev, prev_x_diff, y, y_prev, prev_y_diff, batLeg): """Return 'Pad', 'Pitch' or 'Motion' based on ball & batsman coords.""" if x_prev == 0 and y_prev == 0: return "Motion", 0, 0 if abs(x - x_prev) > 3 * abs(prev_x_diff) and abs(prev_x_diff) > 0: if y < batLeg: return "Pad", x - x_prev, y - y_prev if y - y_prev < 0 and prev_y_diff > 0: if y < batLeg: return "Pad", x - x_prev, y - y_prev else: return "Pitch", x - x_prev, y - y_prev return "Motion", x - x_prev, y - y_prev # --------------------------------------------------- # Main analysis routine wrapped for Gradio # --------------------------------------------------- def detect_lbw(video): """Run the LBW detector on an uploaded video, return annotated clip + verdict.""" # Accept both dict (gradio 4.x) or str video_path = video if isinstance(video, (str, Path)) else video.get("name") cap = cv2.VideoCapture(str(video_path)) if not cap.isOpened(): raise ValueError("Unable to open uploaded video.") fps = cap.get(cv2.CAP_PROP_FPS) or 25 width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # Prepare temporary output file for annotated video tmpfile = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") out_path = tmpfile.name fourcc = cv2.VideoWriter_fourcc(*"mp4v") writer = cv2.VideoWriter(out_path, fourcc, fps, (width, height)) # Tracking variables x = y = batLeg = 0 x_prev = y_prev = 0 prev_x_diff = prev_y_diff = 0 lbw_detected = False while True: x_prev, y_prev = x, y success, img = cap.read() if not success: break overlay = img.copy() # 1️⃣ Ball detection _, x, y = ball_detect(img, mycolorFinder, hsvVals) if x and y: cv2.circle(overlay, (x, y), 8, (255, 0, 0), -1) # 2️⃣ Batsman detection batsmanContours = batsman_detect( img, tuned_rgb_lower, tuned_rgb_upper, tuned_canny_threshold1, tuned_canny_threshold2, ) # Compute batsman's leg (lowest y among contours above the ball) current_batLeg = float("inf") for cnt in batsmanContours: if cv2.contourArea(cnt) > 5000 and y != 0 and min(cnt[:, :, 1]) < y: leg_candidate = max(cnt[:, :, 1]) current_batLeg = min(current_batLeg, leg_candidate) cv2.drawContours(overlay, cnt, -1, (0, 255, 0), 3) batLeg = current_batLeg if current_batLeg != float("inf") else batLeg # 3️⃣ Classify the motion event for this frame motion_type, prev_x_diff, prev_y_diff = ball_pitch_pad( x, x_prev, prev_x_diff, y, y_prev, prev_y_diff, batLeg ) if motion_type == "Pad": lbw_detected = True cv2.putText( overlay, "PAD CONTACT", (50, 80), cv2.FONT_HERSHEY_SIMPLEX, 1.6, (0, 0, 255), 4, cv2.LINE_AA, ) elif motion_type == "Pitch": cv2.putText( overlay, "Bounced", (50, 80), cv2.FONT_HERSHEY_SIMPLEX, 1.6, (0, 255, 255), 4, cv2.LINE_AA, ) writer.write(overlay) cap.release() writer.release() verdict = "✅ Potential LBW Detected!" if lbw_detected else "❌ No LBW Detected." return out_path, verdict # --------------------------------------------------- # Gradio interface # --------------------------------------------------- demo = gr.Interface( fn=detect_lbw, inputs=gr.Video(label="Upload cricket clip (side-on view)"), outputs=[ gr.Video(label="Annotated Review"), gr.Textbox(label="Decision"), ], title="Automated LBW Detector", description=( "Upload a short video of the delivery. The system analyses the ball & batsman " "interaction frame-by-frame, overlays detections, and flags potential LBW instances." ), ) if __name__ == "__main__": demo.launch()