#!/opt/homebrew/bin/python3.11 """ Scan full video frames for stamp-like regions (Blue+Red rectangles) """ import cv2 import numpy as np import os import glob UUID = "384b0ff44aaaa1f1" BASE_DIR = f"output/{UUID}/full_video_scans" OUTPUT_DIR = f"output/{UUID}/stamp_candidates_full" os.makedirs(OUTPUT_DIR, exist_ok=True) print("šŸ” Scanning full video frames for stamps...") frames = sorted(glob.glob(os.path.join(BASE_DIR, "frame_*.jpg"))) print(f"Found {len(frames)} frames to scan.") total_candidates = 0 for frame_path in frames: img = cv2.imread(frame_path) if img is None: continue hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # Detect Blue regions blue_mask = cv2.inRange(hsv, np.array([90, 40, 40]), np.array([130, 255, 255])) # Detect Red regions red_mask1 = cv2.inRange(hsv, np.array([0, 40, 40]), np.array([10, 255, 255])) red_mask2 = cv2.inRange(hsv, np.array([170, 40, 40]), np.array([179, 255, 255])) red_mask = red_mask1 + red_mask2 # Find contours in blue areas contours, _ = cv2.findContours( blue_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE ) frame_candidates = 0 for contour in contours: area = cv2.contourArea(contour) if area < 200 or area > 30000: continue x, y, w, h = cv2.boundingRect(contour) aspect_ratio = w / h if h > 0 else 0 # Stamps are roughly rectangular if aspect_ratio < 0.5 or aspect_ratio > 2.0: continue # Check red content inside roi_red = red_mask[y : y + h, x : x + w] red_pixels = cv2.countNonZero(roi_red) red_ratio = red_pixels / (w * h) if w * h > 0 else 0 if red_ratio > 0.08: frame_candidates += 1 total_candidates += 1 # Save crop crop = img[y : y + h, x : x + w] basename = os.path.basename(frame_path).replace(".jpg", "") crop_name = f"stamp_{basename}_{x}_{y}_red{int(red_ratio * 100)}.jpg" cv2.imwrite(os.path.join(OUTPUT_DIR, crop_name), crop) if frame_candidates > 0: print(f" šŸ“ {os.path.basename(frame_path)}: {frame_candidates} candidates") print(f"\nšŸ Done. Found {total_candidates} total candidates in {OUTPUT_DIR}")