#!/opt/homebrew/bin/python3.11 """ Find BLUE stamps (Inverted Jenny) or Envelopes Filter: Blue Color + Small/Medium Size """ import cv2 import numpy as np import os UUID = "384b0ff44aaaa1f1" BASE_DIR = f"output/{UUID}/florence2_results" # Keyframes to check FRAMES = [ "scan_6751.jpg", # 112:31 "scan_6755.jpg", # 112:35 "scan_6756.jpg", # 112:36 (Dialogue: "Give me the stamp") "scan_6759.jpg", # 112:39 ] print("šŸ” Analyzing Keyframes for BLUE Stamps...") for frame_name in FRAMES: img_path = os.path.join(BASE_DIR, frame_name) if not os.path.exists(img_path): continue img = cv2.imread(img_path) h, w, _ = img.shape # Convert to HSV hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # Blue Mask (Hue ~100-130) # Adjusting for various shades of blue mask1 = cv2.inRange(hsv, np.array([90, 50, 50]), np.array([130, 255, 255])) # Optional: Also look for White/Paper (Envelope) # mask2 = cv2.inRange(hsv, np.array([0, 0, 200]), np.array([180, 30, 255])) # mask = mask1 + mask2 mask = mask1 contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) print(f"\nšŸŽžļø Scanning {frame_name} for Blue objects...") found_count = 0 for cnt in contours: area = cv2.contourArea(cnt) # FILTER 1: Area Size # We want something stamp-sized or envelope-sized # Stamp: ~100 - 5000 px # Envelope: ~1000 - 20000 px if area < 100 or area > 20000: continue # FILTER 2: Aspect Ratio (Rectangular) x, y, w_box, h_box = cv2.boundingRect(cnt) aspect_ratio = float(w_box) / h_box # Check if it looks like a rectangle (0.5 to 2.0 ratio roughly) # But stamps can be small. Let's just check area mostly. # Filter out very long thin lines (likely text) if w_box < 5 or h_box < 5: continue # Filter out very large backgrounds if w_box > 300 and h_box > 300: continue print( f" āœ… Found Blue Candidate: Area={int(area)}, Size={w_box}x{h_box}, Pos=({x},{y})" ) # Draw cv2.rectangle(img, (x, y), (x + w_box, y + h_box), (0, 255, 0), 2) cv2.putText( img, f"BLUE? ({int(area)})", (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1, ) # Crop crop = img[y : y + h_box, x : x + w_box] crop_path = os.path.join(BASE_DIR, f"crop_blue_{frame_name}_{x}_{y}.jpg") cv2.imwrite(crop_path, crop) found_count += 1 if found_count > 0: res_path = os.path.join(BASE_DIR, f"result_blue_{frame_name}") cv2.imwrite(res_path, img) else: print(" āŒ No blue candidates found.")