Spaces:
Runtime error
Runtime error
| import json | |
| import random | |
| import io | |
| from PIL import Image, ImageDraw, ImageFont | |
| import os | |
| from PIL import ImageColor | |
| # Costante per il fattore di normalizzazione usato nelle coordinate | |
| NORMALIZATION_DIVISOR = 1000 | |
| # @title Parsing JSON output | |
| def parse_json(json_output: str): | |
| # Parsing out the markdown fencing | |
| lines = json_output.splitlines() | |
| for i, line in enumerate(lines): | |
| if line == "```json": | |
| json_output = "\n".join(lines[i+1:]) # Remove everything before "```json" | |
| json_output = json_output.split("```")[0] # Remove everything after the closing "```" | |
| break # Exit the loop once "```json" is found | |
| return json_output | |
| # @title Plotting Util | |
| additional_colors = [colorname for (colorname, colorcode) in ImageColor.colormap.items()] | |
| def plot_bounding_boxes(im, bounding_boxes): | |
| """ | |
| Plots bounding boxes on an image with markers for each a name, using PIL, normalized coordinates, and different colors. | |
| Args: | |
| img_path: The path to the image file. | |
| bounding_boxes: A list of bounding boxes containing the name of the object | |
| and their positions in normalized [y1 x1 y2 x2] format. | |
| """ | |
| # Load the image | |
| img = im | |
| width, height = img.size | |
| print(img.size) | |
| # Create a drawing object | |
| draw = ImageDraw.Draw(img) | |
| # Define a list of colors | |
| colors = [ | |
| 'red', | |
| 'green', | |
| 'blue', | |
| 'yellow', | |
| 'orange', | |
| 'pink', | |
| 'purple', | |
| 'brown', | |
| 'gray', | |
| 'beige', | |
| 'turquoise', | |
| 'cyan', | |
| 'magenta', | |
| 'lime', | |
| 'navy', | |
| 'maroon', | |
| 'teal', | |
| 'olive', | |
| 'coral', | |
| 'lavender', | |
| 'violet', | |
| 'gold', | |
| 'silver', | |
| ] + additional_colors | |
| # Parsing out the markdown fencing | |
| bounding_boxes = parse_json(bounding_boxes) | |
| # Iterate over the bounding boxes | |
| for i, bounding_box in enumerate(json.loads(bounding_boxes)): | |
| # Select a color from the list | |
| color = colors[i % len(colors)] | |
| # Convert normalized coordinates to absolute coordinates | |
| abs_y1 = int(bounding_box["box_2d"][0] / NORMALIZATION_DIVISOR * height) | |
| abs_x1 = int(bounding_box["box_2d"][1] / NORMALIZATION_DIVISOR * width) | |
| abs_y2 = int(bounding_box["box_2d"][2] / NORMALIZATION_DIVISOR * height) | |
| abs_x2 = int(bounding_box["box_2d"][3] / NORMALIZATION_DIVISOR * width) | |
| if abs_x1 > abs_x2: | |
| abs_x1, abs_x2 = abs_x2, abs_x1 | |
| if abs_y1 > abs_y2: | |
| abs_y1, abs_y2 = abs_y2, abs_y1 | |
| # Draw the bounding box | |
| draw.rectangle( | |
| ((abs_x1, abs_y1), (abs_x2, abs_y2)), outline=color, width=4 | |
| ) | |
| # Draw the text | |
| if "label" in bounding_box: | |
| draw.text((abs_x1 + 8, abs_y1 + 6), bounding_box["label"], fill=color) | |
| # Display the image | |
| img.show() | |
| def save_cropped_images( | |
| im: Image.Image, bounding_boxes_json_str: str, output_folder: str = "output_llm" | |
| ) -> list[str]: | |
| """ | |
| Ritaglia oggetti da un'immagine in base alle bounding box e li salva in una cartella specificata. | |
| Args: | |
| im: L'oggetto PIL.Image. | |
| bounding_boxes_json_str: Una stringa JSON contenente le bounding box. | |
| Ogni box dovrebbe avere "label" e "box_2d" | |
| (coordinate normalizzate [y1, x1, y2, x2] su base NORMALIZATION_DIVISOR). | |
| output_folder: La cartella dove verranno salvate le immagini ritagliate. Default "files". | |
| Returns: | |
| list[str]: Una lista dei percorsi ai file delle immagini ritagliate salvate con successo. | |
| """ | |
| saved_file_paths = [] | |
| os.makedirs(output_folder, exist_ok=True) | |
| width, height = im.size | |
| # Parsing della stringa JSON | |
| parsed_json_str = parse_json(bounding_boxes_json_str) | |
| try: | |
| bounding_boxes_list = json.loads(parsed_json_str) | |
| except json.JSONDecodeError as e: | |
| print(f"Errore nel decodificare JSON: {e}") | |
| return saved_file_paths # Ritorna lista vuota in caso di errore JSON iniziale | |
| filename_counts = {} # Per gestire etichette duplicate | |
| for i, bounding_box in enumerate(bounding_boxes_list): | |
| if "box_2d" not in bounding_box: | |
| print(f"Bounding box {i} saltata: chiave 'box_2d' mancante.") | |
| continue | |
| if len(bounding_box["box_2d"]) != 4: | |
| print(f"Bounding box {i} saltata: 'box_2d' non ha 4 coordinate.") | |
| continue | |
| # Converte coordinate normalizzate in coordinate assolute | |
| # box_2d è [y1, x1, y2, x2] | |
| abs_y1 = round(bounding_box["box_2d"][0] / NORMALIZATION_DIVISOR * height) | |
| abs_x1 = round(bounding_box["box_2d"][1] / NORMALIZATION_DIVISOR * width) | |
| abs_y2 = round(bounding_box["box_2d"][2] / NORMALIZATION_DIVISOR * height) | |
| abs_x2 = round(bounding_box["box_2d"][3] / NORMALIZATION_DIVISOR * width) | |
| # Assicura che abs_x1 sia sinistra, abs_x2 destra, abs_y1 alto, abs_y2 basso | |
| # per la funzione crop di PIL che richiede (left, upper, right, lower) | |
| crop_left = min(abs_x1, abs_x2) | |
| crop_upper = min(abs_y1, abs_y2) | |
| crop_right = max(abs_x1, abs_x2) | |
| crop_lower = max(abs_y1, abs_y2) | |
| if crop_left >= crop_right or crop_upper >= crop_lower: | |
| label_for_log = bounding_box.get('label', f'indice {i}') | |
| print(f"Bounding box per '{label_for_log}' saltata: area nulla ({crop_left},{crop_upper},{crop_right},{crop_lower})") | |
| continue | |
| cropped_image = im.crop((crop_left, crop_upper, crop_right, crop_lower)) | |
| label = bounding_box.get("label", f"unlabeled_crop_{i}") | |
| safe_label = "".join(c for c in label if c.isalnum() or c in (' ', '_', '-')).strip().replace(' ', '_') | |
| if not safe_label: | |
| safe_label = f"unlabeled_crop_{i}" | |
| count = filename_counts.get(safe_label, 0) | |
| filename_counts[safe_label] = count + 1 | |
| output_filename = f"{safe_label}_{count}.png" if count > 0 else f"{safe_label}.png" | |
| output_path = os.path.join(output_folder, output_filename) | |
| try: | |
| cropped_image.save(output_path) | |
| saved_file_paths.append(output_path) | |
| except Exception as e: | |
| print(f"Errore nel salvare l'immagine {output_path}: {e}") | |
| return saved_file_paths |