#!/opt/homebrew/bin/python3.11 """ Find SMALL red triangles (Stamps) using OpenCV Filter: Triangle Shape + Small Area (Physical Constraint) """ import cv2 import numpy as np import os UUID = "384b0ff44aaaa1f1" BASE_DIR = f"output/{UUID}/florence2_results" # Check the original frame IMG_NAME = "frame_6756.jpg" IMG_PATH = os.path.join(BASE_DIR, IMG_NAME) OUT_PATH = os.path.join(BASE_DIR, "found_small_stamp_opencv.jpg") print(f"🔍 Analyzing {IMG_NAME} for SMALL stamps...") if not os.path.exists(IMG_PATH): print("❌ Image not found.") exit() img = cv2.imread(IMG_PATH) h, w, _ = img.shape print(f"📐 Image Size: {w}x{h}") # 1. Convert to HSV hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 2. Red Mask mask1 = cv2.inRange(hsv, np.array([0, 70, 50]), np.array([10, 255, 255])) mask2 = cv2.inRange(hsv, np.array([170, 70, 50]), np.array([180, 255, 255])) mask = mask1 + mask2 # 3. Find Contours contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) print(f"🔍 Found {len(contours)} red regions.") found_stamps = [] # Screen area approx 2 million pixels. Stamp should be tiny (< 1% or < 15,000 pixels) MAX_STAMP_AREA = 15000 for cnt in contours: area = cv2.contourArea(cnt) # Physical Constraint: Must be small if area > MAX_STAMP_AREA: continue # Shape Constraint: Must be triangle-like (approx 3 vertices) peri = cv2.arcLength(cnt, True) approx = cv2.approxPolyDP(cnt, 0.04 * peri, True) if len(approx) == 3: x, y, w_box, h_box = cv2.boundingRect(approx) found_stamps.append((x, y, w_box, h_box, approx, area)) print(f"✅ Potential Stamp: Area={area}, Box=({x},{y})") # 4. Draw Results result_img = img.copy() for x, y, w_box, h_box, approx, area in found_stamps: cv2.rectangle(result_img, (x, y), (x + w_box, y + h_box), (0, 255, 0), 2) cv2.drawContours(result_img, [approx], 0, (255, 0, 0), 2) cv2.putText( result_img, f"STAMP ({area})", (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1, ) if found_stamps: cv2.imwrite(OUT_PATH, result_img) print(f"🎨 Result saved to: {OUT_PATH}") # Crop the first one x, y, w_box, h_box, _, _ = found_stamps[0] crop = img[y : y + h_box, x : x + w_box] cv2.imwrite(os.path.join(BASE_DIR, "crop_small_stamp.jpg"), crop) else: print("❌ No small stamps found in this frame.")