import cv2 from cvzone.ColorModule import ColorFinder def ball_detect(img, color_finder, hsv_values): """ Detects a ball in an image frame based on color. Adapted to handle OpenCV-style contours (NumPy arrays of points). Args: img: The input image frame (BGR format). color_finder: An instance of cvzone.ColorFinder for color detection. hsv_values: A dictionary containing HSV range for ball color. Returns: tuple: (img_with_contours, ball_x, ball_y) - img_with_contours: Image with contours drawn around the detected ball (or None if no ball detected). - ball_x, ball_y: Center coordinates (x, y) of the detected ball (or 0, 0 if no ball detected). """ ball_x = 0 ball_y = 0 img_with_contours = None if img is None: return None, ball_x, ball_y imggray_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) _, mask = color_finder.update(imggray_hsv, hsv_values) contours, _ = cv2.findContours( mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE ) # Use standard cv2.findContours # print(f"Type of contours: {type(contours)}") # Keep for debugging - should be NumPy array if len(contours) > 0: # Find the contour with the largest area using cv2.contourArea largest_contour_index = 0 max_area = 0 for i, contour in enumerate(contours): area = cv2.contourArea(contour) if area > max_area: max_area = area largest_contour_index = i largest_contour = contours[largest_contour_index] # Calculate centroid using moments (OpenCV method for center of contour) M = cv2.moments(largest_contour) if M["m00"] != 0: # avoid division by zero ball_x = int(M["m10"] / M["m00"]) ball_y = int(M["m01"] / M["m00"]) else: ball_x = 0 ball_y = 0 img_with_contours = img.copy() cv2.drawContours( img_with_contours, [largest_contour], -1, (255, 0, 0), 2 ) # Draw largest contour cv2.circle( img_with_contours, (ball_x, ball_y), 5, (255, 0, 0), -1 ) # Draw center point return img_with_contours, ball_x, ball_y if __name__ == "__main__": cap = cv2.VideoCapture(r"lbw.mp4") color_finder = ColorFinder(False) hsv_vals = { "hmin": 10, "smin": 44, "vmin": 192, "hmax": 125, "smax": 114, "vmax": 255, } while True: frame, img = cap.read() if not frame: break img_contours, x, y = ball_detect(img, color_finder, hsv_vals) if img_contours is not None: cv2.imshow("Ball Detection", img_contours) else: cv2.imshow("Ball Detection", img) if cv2.waitKey(1) & 0xFF == ord("q"): break cap.release() cv2.destroyAllWindows()