Spaces:
Sleeping
Sleeping
Subida inicial del proyecto
Browse files
app.py
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
# Cargue de libreria necesarias
|
| 3 |
+
|
| 4 |
+
from transformers import DetrImageProcessor, DetrForObjectDetection
|
| 5 |
+
import torch
|
| 6 |
+
from PIL import Image
|
| 7 |
+
import gradio as gr
|
| 8 |
+
|
| 9 |
+
#transformers: librería de Hugging Face que tiene modelos ya entrenados como DETR.
|
| 10 |
+
# DetrImageProcessor: se encarga de preprocesar la imagen para que el modelo la entienda.
|
| 11 |
+
# DetrForObjectDetection: es el modelo DETR entrenado.
|
| 12 |
+
# torch: es PyTorch, la librería para hacer cálculos con redes neuronales.
|
| 13 |
+
# PIL.Image: permite trabajar con imágenes en Python.
|
| 14 |
+
# gradio: sirve para hacer una interfaz gráfica web sencilla y probar el modelo.
|
| 15 |
+
|
| 16 |
+
#----------------------------------------------------------------------------------------------------------
|
| 17 |
+
|
| 18 |
+
# Cargar el procesador y el modelo
|
| 19 |
+
processor = DetrImageProcessor.from_pretrained("facebook/detr-resnet-50")
|
| 20 |
+
model = DetrForObjectDetection.from_pretrained("facebook/detr-resnet-50")
|
| 21 |
+
|
| 22 |
+
# Explicación:
|
| 23 |
+
# Aquí cargamos un modelo ya entrenado de Hugging Face: facebook/detr-resnet-50.
|
| 24 |
+
# No necesitamos entrenar nada desde cero, porque este modelo ya sabe detectar objetos comunes (personas, perros, autos, etc.).
|
| 25 |
+
# processor prepara la imagen (redimensionar, normalizar).
|
| 26 |
+
# model es el “cerebro” que detecta objetos.
|
| 27 |
+
|
| 28 |
+
# Decisión tomada: usamos un modelo preentrenado porque entrenar uno desde cero requiere millones de imágenes y mucho poder de cómputo. Con Hugging Face podemos reutilizar un modelo listo.
|
| 29 |
+
|
| 30 |
+
#--------------------------------------------------------------------------------------------------------
|
| 31 |
+
|
| 32 |
+
# Función para procesar la imagen
|
| 33 |
+
def detect_objects(image):
|
| 34 |
+
# Preprocesamiento
|
| 35 |
+
inputs = processor(images=image, return_tensors="pt")
|
| 36 |
+
|
| 37 |
+
# Explicación:
|
| 38 |
+
|
| 39 |
+
# La función detect_objects será la encargada de recibir una imagen y devolver qué objetos encontró.
|
| 40 |
+
# processor convierte la imagen en tensores (estructuras numéricas que entiende PyTorch).
|
| 41 |
+
# return_tensors="pt" indica que los tensores se hacen para PyTorch (pt = pytorch).
|
| 42 |
+
# Decisión tomada: usamos processor en lugar de hacer manualmente redimensionar/normalizar la imagen porque así evitamos errores y aprovechamos la configuración estándar del modelo.
|
| 43 |
+
|
| 44 |
+
#--------------------------------------------------------------------------------------------------------
|
| 45 |
+
|
| 46 |
+
# Detectar objetos
|
| 47 |
+
with torch.no_grad():
|
| 48 |
+
outputs = model(**inputs)
|
| 49 |
+
|
| 50 |
+
# Explicación:
|
| 51 |
+
|
| 52 |
+
# torch.no_grad() desactiva el cálculo de gradientes porque no vamos a entrenar, solo a usar el modelo.
|
| 53 |
+
# model(**inputs) corre la imagen por la red neuronal y devuelve predicciones:
|
| 54 |
+
# qué objetos cree que hay
|
| 55 |
+
# dónde están ubicados
|
| 56 |
+
|
| 57 |
+
# Decisión tomada: usar no_grad() ahorra memoria y acelera la ejecución, ideal para inferencia.
|
| 58 |
+
|
| 59 |
+
#--------------------------------------------------------------------------------------------------------
|
| 60 |
+
|
| 61 |
+
# Filtrar resultados
|
| 62 |
+
target_sizes = torch.tensor([image.size[::-1]]) # (alto, ancho)
|
| 63 |
+
results = processor.post_process_object_detection(outputs, target_sizes=target_sizes, threshold=0.9)[0]
|
| 64 |
+
|
| 65 |
+
# Explicación:
|
| 66 |
+
|
| 67 |
+
# image.size[::-1]: invierte el orden del tamaño de la imagen (porque PIL usa (ancho, alto) y el modelo espera (alto, ancho)).
|
| 68 |
+
# post_process_object_detection: convierte las predicciones crudas en resultados entendibles:
|
| 69 |
+
# nombres de clases (ej: "dog", "car").
|
| 70 |
+
# puntaje de confianza (score).
|
| 71 |
+
# cajas delimitadoras (boxes) que marcan dónde está el objeto.
|
| 72 |
+
# threshold=0.9: solo se aceptan predicciones con 90% de confianza o más.
|
| 73 |
+
|
| 74 |
+
# Decisión tomada: se fija un umbral alto (0.9) para reducir falsos positivos. Si bajamos a 0.5, detectaría más objetos, pero también más errores.
|
| 75 |
+
|
| 76 |
+
#-------------------------------------------------------------------------------------------------------
|
| 77 |
+
|
| 78 |
+
# Crear una lista de los resultados con nombre y puntuación
|
| 79 |
+
labels = results["labels"]
|
| 80 |
+
scores = results["scores"]
|
| 81 |
+
boxes = results["boxes"]
|
| 82 |
+
|
| 83 |
+
# Mostrar los objetos detectados
|
| 84 |
+
detected_objects = []
|
| 85 |
+
for score, label, box in zip(scores, labels, boxes):
|
| 86 |
+
detected_objects.append(f"Objeto: {label}, Score: {score:.2f}, Box: {box.tolist()}")
|
| 87 |
+
|
| 88 |
+
return "\n".join(detected_objects)
|
| 89 |
+
|
| 90 |
+
# Explicación:
|
| 91 |
+
|
| 92 |
+
# labels: números que representan clases de objetos (ejemplo: 1 = persona, 17 = gato).
|
| 93 |
+
# scores: probabilidad de que el objeto detectado sea correcto.
|
| 94 |
+
# boxes: coordenadas de las cajas que enmarcan al objeto.
|
| 95 |
+
# Luego se arma un texto con los resultados:
|
| 96 |
+
# Objeto: 1, Score: 0.98, Box: [12, 34, 200, 300]
|
| 97 |
+
|
| 98 |
+
# Decisión tomada: mostrar los resultados como texto para entender primero qué devuelve el modelo. Después podemos mejorarlo para dibujar cajas en la imagen (más visual).
|
| 99 |
+
|
| 100 |
+
#-----------------------------------------------------------------------------------------------------
|
| 101 |
+
|
| 102 |
+
# Paso 4: Crear interfaz con Gradio
|
| 103 |
+
# --------------------------------------------
|
| 104 |
+
def create_interface():
|
| 105 |
+
interface = gr.Interface(
|
| 106 |
+
fn=detect_objects, # función que conecta la app con el modelo
|
| 107 |
+
inputs=gr.Image(type="pil"), # entrada: imagen cargada por el usuario
|
| 108 |
+
outputs=gr.Textbox(), # salida: resultados en formato texto
|
| 109 |
+
live=True, # procesa inmediatamente al cargar
|
| 110 |
+
title="Detección de Objetos con Transformers",
|
| 111 |
+
description="Sube una imagen y descubre qué objetos detecta el modelo DETR."
|
| 112 |
+
)
|
| 113 |
+
|
| 114 |
+
interface.launch()
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
# --------------------------------------------
|
| 118 |
+
# Paso 4: Crear interfaz con Gradio
|
| 119 |
+
|
| 120 |
+
def create_interface():
|
| 121 |
+
interface = gr.Interface(
|
| 122 |
+
fn=detect_objects, # función que conecta la app con el modelo
|
| 123 |
+
inputs=gr.Image(type="pil"), # entrada: imagen cargada por el usuario
|
| 124 |
+
outputs=gr.Textbox(), # salida: resultados en formato texto
|
| 125 |
+
live=True, # procesa inmediatamente al cargar
|
| 126 |
+
title="Detección de Objetos con Transformers",
|
| 127 |
+
description="Sube una imagen y descubre qué objetos detecta el modelo DETR."
|
| 128 |
+
)
|
| 129 |
+
|
| 130 |
+
interface.launch()
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
# --------------------------------------------
|
| 134 |
+
# Ejecutar la aplicación
|
| 135 |
+
# --------------------------------------------
|
| 136 |
+
if __name__ == "__main__":
|
| 137 |
+
create_interface()
|
| 138 |
+
|
| 139 |
+
# Interfaz con Gradio (create_interface())
|
| 140 |
+
# Permite subir imágenes y ver los resultados.
|
| 141 |
+
# Entrada: gr.Image(type="pil").
|
| 142 |
+
# Salida: gr.Textbox() con los objetos detectados.
|
| 143 |
+
# live=True: procesa apenas se carga la imagen.
|
| 144 |
+
# Ejecución (if __name__ == "__main__":)
|
| 145 |
+
# Se asegura que la aplicación solo corra al ejecutar python app.py.
|