Spaces:
Sleeping
Sleeping
| # -*- coding: utf-8 -*- | |
| # app.py - Versi贸n integrada con detecci贸n, clasificaci贸n y visualizaci贸n | |
| # Importamos las librer铆as necesarias | |
| import gradio as gr | |
| from PIL import Image, ImageDraw # Import ImageDraw for drawing on images | |
| import numpy as np | |
| from transformers import pipeline # Make sure transformers is installed (pip install transformers) | |
| # --- Cargar Modelos --- | |
| # Cargar el modelo de detecci贸n de objetos | |
| # Este modelo es general, necesitamos verificar si detecta la fruta deseada (ej. 'apple') | |
| try: | |
| object_detector = pipeline("object-detection", model="facebook/detr-resnet-50") | |
| print("Object detection model loaded successfully.") | |
| except Exception as e: | |
| print(f"Error loading object detection model: {e}") | |
| object_detector = None | |
| # Cargar el modelo de clasificaci贸n de im谩genes (el elegido por el usuario) | |
| # Este modelo deber铆a estar entrenado para las clases relevantes (ej. madurez, variedad) | |
| try: | |
| clasificador = pipeline("image-classification", model="apple/mobilevit-small") | |
| print("Image classification model (apple/mobilevit-small) loaded successfully.") | |
| except Exception as e: | |
| print(f"Error loading image classification model: {e}") | |
| clasificador = None | |
| # --- Funci贸n de Procesamiento --- | |
| def clasificar_madurez_with_box(imagen: Image.Image): | |
| """ | |
| Procesa una imagen: detecta objetos, selecciona el m谩s relevante (fruta), | |
| lo clasifica y dibuja un recuadro en la imagen original. | |
| Args: | |
| imagen: Objeto PIL Image de la imagen de entrada. | |
| Returns: | |
| Una tupla con la imagen modificada (con recuadro) y una cadena de texto con los resultados. | |
| Retorna None para la imagen si no hay entrada v谩lida. | |
| """ | |
| if imagen is None: | |
| # Return None for the image output when no image is uploaded | |
| return None, "Por favor, sube una imagen." | |
| # Create a copy of the image to draw on | |
| image_with_box = imagen.copy() | |
| draw = ImageDraw.Draw(image_with_box) | |
| text_output = "" # Initialize text output | |
| if object_detector is None: | |
| text_output = "Error: el modelo de detecci贸n de objetos no pudo cargarse." | |
| # Return the original image and an error message if detector fails | |
| return imagen, text_output | |
| try: | |
| # Realizar detecci贸n de objetos | |
| detections = object_detector(inputs=imagen) | |
| print("Object detection results:", detections) | |
| # TODO: Ajustar 'target_fruit_label' seg煤n las etiquetas reales del modelo DETR | |
| # y el tipo de fruta espec铆fico del proyecto (ej. 'apple', 'orange', etc.) | |
| target_fruit_label = 'apple' | |
| # Filtrar por detecciones con confianza > 0.5 y la etiqueta objetivo | |
| # Es CRUCIAL verificar qu茅 etiquetas produce 'facebook/detr-resnet-50' | |
| # para la fruta deseada. Podr铆a ser necesario ajustar este filtro. | |
| relevant_fruits = [det for det in detections if det['label'] == target_fruit_label and det['score'] > 0.5] | |
| if not relevant_fruits: | |
| text_output = f"No se detectaron objetos de tipo '{target_fruit_label}' en la imagen con suficiente confianza." | |
| # Return the original image when no relevant fruits are found | |
| return imagen, text_output | |
| # Funci贸n para calcular el 谩rea de la caja delimitadora | |
| def get_box_area(box): | |
| return (box['xmax'] - box['xmin']) * (box['ymax'] - box['ymin']) | |
| # Seleccionar el objeto m谩s relevante (el de mayor 谩rea en este caso simple) | |
| most_relevant_fruit = max(relevant_fruits, key=lambda det: get_box_area(det['box'])) | |
| box = most_relevant_fruit['box'] | |
| xmin, ymin, xmax, ymax = box['xmin'], box['ymin'], box['xmax'], box['ymax'] | |
| # Dibujar el recuadro en la copia de la imagen | |
| # Las coordenadas deben ser enteros para ImageDraw | |
| draw.rectangle([(int(xmin), int(ymin)), (int(xmax), int(ymax))], outline="blue", width=5) # Grosor del recuadro | |
| # Recortar la imagen a la caja delimitadora del objeto detectado | |
| cropped_fruit_img = imagen.crop((int(xmin), int(ymin), int(xmax), int(ymax))) | |
| # Pasar la imagen recortada al modelo de clasificaci贸n | |
| if clasificador is None: | |
| text_output = "Error: el modelo de clasificaci贸n no pudo cargarse." | |
| # Return the image with the box drawn, and the classification error | |
| return image_with_box, text_output | |
| try: | |
| clasificacion_resultados = clasificador(inputs=cropped_fruit_img) | |
| print("Classification results on cropped image:", clasificacion_resultados) | |
| if clasificacion_resultados: | |
| # El modelo apple/mobilevit-small tiene etiquetas espec铆ficas. | |
| # Necesitamos ver cu谩les son para interpretar el resultado correctamente. | |
| # Por ahora, tomamos el primer resultado. | |
| mejor_prediccion = clasificacion_resultados[0] | |
| label = mejor_prediccion['label'] # Etiqueta predicha por mobilevit-small | |
| confianza = mejor_prediccion['score'] # Puntuaci贸n de confianza | |
| # Combinar detecci贸n y clasificaci贸n en la salida de texto | |
| text_output = ( | |
| f"Objeto detectado (tipo DETR: '{most_relevant_fruit['label']}', " | |
| f"Confianza detecci贸n: {most_relevant_fruit['score']:.2f}, " | |
| f"脕rea: {get_box_area(box):.0f}).\n\n" | |
| f"Clasificado por mobilevit-small como: '{label}' " | |
| f"(Confianza clasificaci贸n: {confianza:.2f})." | |
| ) | |
| else: | |
| text_output = f"Objeto detectado de tipo '{target_fruit_label}', pero el modelo de clasificaci贸n no pudo clasificarlo." | |
| except Exception as e: | |
| text_output = f"Ocurri贸 un error durante la clasificaci贸n del objeto detectado: {e}" | |
| # Return the image with the box drawn, and the classification error | |
| return image_with_box, text_output | |
| except Exception as e: | |
| text_output = f"Ocurri贸 un error durante la detecci贸n de objetos: {e}" | |
| # Return the original image and the detection error | |
| return imagen, text_output | |
| # Retornar tanto la imagen modificada como la salida de texto | |
| return image_with_box, text_output | |
| # --- Definici贸n de la Interfaz de Gradio --- | |
| interfaz = gr.Interface( | |
| fn=clasificar_madurez_with_box, # Usamos la funci贸n que devuelve imagen y texto | |
| inputs=gr.Image(type="pil", label="Sube una imagen de fruta"), # Componente de entrada de imagen | |
| # Las salidas son una lista de componentes de Gradio | |
| outputs=[ | |
| gr.Image(type="pil", label="Imagen con fruta detectada"), # Salida para la imagen con recuadro | |
| "text" # Salida para el texto de resultados | |
| ], | |
| title="Clasificador de Frutas (MVP Agro)", # T铆tulo de la interfaz | |
| description="Sube una foto de una fruta (idealmente una manzana) y la IA intentar谩 detectarla y clasificarla usando mobilevit-small." # Descripci贸n | |
| ) | |
| # --- Lanzar la Interfaz --- | |
| # Esta condici贸n asegura que interfaz.launch() solo se llame cuando el script se ejecuta directamente | |
| # (煤til si esto fuera un archivo .py). En Colab, lanzar directamente funciona. | |
| if __name__ == "__main__": | |
| interfaz.launch() |