#!/opt/homebrew/bin/python3.11 """ Find Stamps by detecting Hands first """ import cv2 import numpy as np import os UUID = "384b0ff44aaaa1f1" BASE_DIR = f"output/{UUID}/florence2_results" # Frames to check FRAMES = [ "scan_6756.jpg", # 112:36 "scan_6763.jpg", # 112:43 "scan_6790.jpg", # 113:10 "scan_6813.jpg", # 113:33 "scan_6832.jpg", # 113:52 ] print("šŸ–ļø Searching for Stamps via Hand Detection...") 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) hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # Skin Color Range (Approximate for Caucasian skin) # Hue: 0-30 (Red/Orange/Yellowish), Sat: 30-200, Val: 50-255 mask = cv2.inRange(hsv, np.array([0, 30, 50]), np.array([30, 200, 255])) # Morphological operations to clean up kernel = np.ones((5, 5), np.uint8) mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) # Find contours (Hands) contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) print(f"\nšŸŽžļø Scanning {frame_name} for hands...") hand_count = 0 for cnt in contours: area = cv2.contourArea(cnt) x, y, w, h = cv2.boundingRect(cnt) # Filter for hand-like size and shape # Hand area: 1000 - 20000 pixels # Aspect ratio: roughly 1:1 to 2:3 if 1000 < area < 30000: aspect_ratio = float(w) / h if 0.3 < aspect_ratio < 2.5: hand_count += 1 print( f" šŸ–ļø Hand Candidate found: Area={int(area)}, Pos=({x},{y}), Size={w}x{h}" ) # Crop Hand hand_crop = img[y : y + h, x : x + w] hand_crop_path = os.path.join( BASE_DIR, f"hand_{frame_name}_{hand_count}.jpg" ) cv2.imwrite(hand_crop_path, hand_crop) # Draw on main image cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 3) # Analyze Hand for Stamp Colors # Stamp is Inverted Jenny: Blue Background, Red Plane # Look for Blue or Pink/Red blobs inside the hand hand_hsv = cv2.cvtColor(hand_crop, cv2.COLOR_BGR2HSV) # 1. Look for Blue (Background) blue_mask = cv2.inRange( hand_hsv, np.array([90, 50, 50]), np.array([130, 255, 255]) ) # 2. Look for Pink/Red (Plane) pink_mask = cv2.inRange( hand_hsv, np.array([150, 50, 50]), np.array([179, 255, 255]) ) blue_area = cv2.countNonZero(blue_mask) pink_area = cv2.countNonZero(pink_mask) # Heuristic: If we find significant Blue and Pink areas in the hand if blue_area > 50 and pink_area > 20: print( f" āœ… Potential Stamp in Hand! (Blue={blue_area}, Pink={pink_area})" ) cv2.putText( img, f"STAMP? ({blue_area})", (x, y + h + 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, ) cv2.imwrite( os.path.join( BASE_DIR, f"found_stamp_hand_{frame_name}_{hand_count}.jpg" ), hand_crop, ) if hand_count == 0: print(" āŒ No hands found.") res_path = os.path.join(BASE_DIR, f"result_hands_{frame_name}") cv2.imwrite(res_path, img)