#!/opt/homebrew/bin/python3.11 """ Find ALL Stamps in the Image using Florence-2 """ import os import cv2 from PIL import Image from transformers import AutoProcessor, AutoModelForCausalLM UUID = "384b0ff44aaaa1f1" OUTPUT_DIR = f"output/{UUID}/florence2_results" INPUT_IMG = os.path.join(OUTPUT_DIR, f"raw_6846.jpg") OUTPUT_IMG = os.path.join(OUTPUT_DIR, f"all_stamps_detected.jpg") # Patch for compatibility (Same as before) import types def patch_model(model): inner_model = model.language_model original_prepare = inner_model.prepare_inputs_for_generation def patched_prepare( self, input_ids, past_key_values=None, attention_mask=None, inputs_embeds=None, **kwargs, ): is_valid_cache = False if past_key_values is not None: if isinstance(past_key_values, (list, tuple)) and len(past_key_values) > 0: first_layer = past_key_values[0] if first_layer is not None and ( not isinstance(first_layer, (list, tuple)) or len(first_layer) > 0 ): is_valid_cache = True if not is_valid_cache: return { "input_ids": input_ids, "attention_mask": attention_mask, "past_key_values": None, "use_cache": True, } else: return original_prepare( input_ids, past_key_values=past_key_values, attention_mask=attention_mask, inputs_embeds=inputs_embeds, **kwargs, ) inner_model.prepare_inputs_for_generation = types.MethodType( patched_prepare, inner_model ) print(f"šŸ“· Loading image from {INPUT_IMG}...") if not os.path.exists(INPUT_IMG): print("āŒ Image not found.") exit() image = Image.open(INPUT_IMG).convert("RGB") print(f"šŸ“ Image Size: {image.width}x{image.height}") print("🧠 Loading Florence-2 model...") try: processor = AutoProcessor.from_pretrained( "microsoft/Florence-2-base", trust_remote_code=True ) model = AutoModelForCausalLM.from_pretrained( "microsoft/Florence-2-base", trust_remote_code=True, attn_implementation="eager" ) patch_model(model) prompt = "" text_input = "stamp" print(f"šŸ” Scanning for '{text_input}'...") inputs = processor(text=prompt, images=image, return_tensors="pt") generated_ids = model.generate( input_ids=inputs["input_ids"], pixel_values=inputs["pixel_values"], max_new_tokens=2048, num_beams=3, ) generated_text = processor.batch_decode(generated_ids, skip_special_tokens=False)[0] # Parse result parsed_answer = processor.post_process_generation( generated_text, task=prompt, image_size=(image.width, image.height) ) print(f"šŸ“¦ Raw Parsed Data: {parsed_answer}") results = parsed_answer.get("", {}) bboxes = results.get("bboxes", []) labels = results.get("bboxes_labels", []) print(f"āœ… Found {len(bboxes)} stamp(s)!") # Draw results img_cv = cv2.imread(INPUT_IMG) colors = [ (0, 255, 0), (255, 0, 0), (0, 0, 255), (255, 255, 0), ] # Green, Blue, Red, Yellow for i, (box, label) in enumerate(zip(bboxes, labels)): x1, y1, x2, y2 = map(int, box) color = colors[i % len(colors)] # Draw box cv2.rectangle(img_cv, (x1, y1), (x2, y2), color, 4) # Draw label background text = f"{label} {i + 1}" (tw, th), _ = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, 1, 2) cv2.rectangle(img_cv, (x1, y1 - th - 10), (x1 + tw + 10, y1), color, -1) # Draw text cv2.putText( img_cv, text, (x1 + 5, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2 ) print(f" šŸ“ Stamp #{i + 1} at ({x1}, {y1}) -> ({x2}, {y2})") cv2.imwrite(OUTPUT_IMG, img_cv) print(f"\nšŸŽØ Image with all detections saved to: {OUTPUT_IMG}") except Exception as e: print(f"āŒ Error: {e}") import traceback traceback.print_exc()