Detección de objetos zero-shot con imágenes de ciencia participativa#
La detección de objetos es una herramienta poderosa para encontrar patrones en imágenes. Muchos proyectos de ciencia participativa, como NASA GLOBE e iNaturalist, incluyen fotografías. Podemos utilizar modelos abiertos de detección de objetos para identificar elementos, como animales y plantas, en estas imágenes.
# Instalar las bibliotecas necesarias
!pip install -q transformers pillow matplotlib torch
import requests
from PIL import Image, ImageDraw, ImageFont
import matplotlib.pyplot as plt
import torch
from transformers import pipeline
print("Bibliotecas importadas")
# Cargar el modelo de detección de objetos zero-shot
# OWL-ViT es un transformador de visión entrenado para la detección con vocabulario abierto
print("Cargando el modelo OWL-ViT... Esto puede tardar un momento.")
checkpoint = "google/owlvit-base-patch32"
detector = pipeline(model=checkpoint, task="zero-shot-object-detection")
def load_image(source):
"""Carga una imagen desde una URL o desde un archivo local."""
try:
if source.startswith(("http://", "https://")):
response = requests.get(source, stream=True, timeout=30)
response.raise_for_status()
image = Image.open(response.raw)
else:
image = Image.open(source)
return image.convert("RGB")
except Exception as e:
print(f"Error al cargar la imagen: {e}")
return None
def draw_detections(image, predictions, threshold=0.1):
"""
Dibuja recuadros delimitadores alrededor de los objetos detectados.
Argumentos:
image: imagen de PIL
predictions: lista de diccionarios con las detecciones
threshold: puntuación mínima de confianza que se mostrará (0-1)
"""
# Crear una copia de la imagen para dibujar sobre ella
draw_image = image.copy()
draw = ImageDraw.Draw(draw_image)
# Intentar cargar una fuente; usar la predeterminada si no está disponible
try:
font = ImageFont.truetype(
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
16
)
except Exception:
font = ImageFont.load_default()
# Filtrar las predicciones según el umbral de confianza
filtered_predictions = [
prediction
for prediction in predictions
if prediction["score"] >= threshold
]
# Dibujar cada detección
for prediction in filtered_predictions:
box = prediction["box"]
score = prediction["score"]
label = prediction["label"]
# Extraer las coordenadas
xmin = box["xmin"]
ymin = box["ymin"]
xmax = box["xmax"]
ymax = box["ymax"]
# Dibujar el recuadro delimitador
draw.rectangle([xmin, ymin, xmax, ymax], outline="red", width=3)
# Crear la etiqueta con la puntuación de confianza
text = f"{label}: {score:.2f}"
# Dibujar el fondo y el texto de la etiqueta
text_bbox = draw.textbbox((xmin, ymin), text, font=font)
draw.rectangle(text_bbox, fill="red")
draw.text((xmin, ymin), text, fill="white", font=font)
return draw_image, len(filtered_predictions)
def run_detection(candidates, image_urls, threshold=0.2):
for idx, source in enumerate(image_urls, 1):
print(f"\nProcesando imagen {idx}/{len(image_urls)}")
print(f"Fuente: {source}")
# Cargar la imagen
image = load_image(source)
if image is None:
continue
print(f"Tamaño de la imagen: {image.size}")
# Ejecutar la detección
print("Detectando objetos...")
predictions = detector(image, candidate_labels=candidates)
# Dibujar las detecciones sobre la imagen
result_image, num_detections = draw_detections(
image,
predictions,
threshold
)
# Mostrar los resultados
print(
f"- Se encontraron {num_detections} objetos "
f"(confianza ≥ {threshold})"
)
# Mostrar la imagen original y la imagen con detecciones
fig, axes = plt.subplots(1, 2, figsize=(16, 8))
axes[0].imshow(image)
axes[0].set_title(
"Imagen original",
fontsize=14,
fontweight="bold"
)
axes[0].axis("off")
axes[1].imshow(result_image)
axes[1].set_title(
f"Detecciones (umbral={threshold})",
fontsize=14,
fontweight="bold"
)
axes[1].axis("off")
plt.tight_layout()
plt.show()
print("-" * 50)
print("Modelo cargado")
Probemos el modelo con algunas fotografías. Primero, cargaremos una imagen de una abeja de iNaturalist, una plataforma donde cualquier persona puede registrar fotografías y observaciones de la naturaleza. Puedes explorar más fotografías de iNaturalist aquí.
Para obtener la URL, haz clic con el botón derecho sobre una imagen y selecciona Copiar dirección de imagen.
# Objetos candidatos a detectar
# Las etiquetas en inglés suelen producir mejores resultados con este modelo
candidates = [
"bee"
]
# URL de la imagen que se analizará; puedes agregar varias
image_urls = [
"https://inaturalist-open-data.s3.amazonaws.com/photos/639462446/large.jpg",
]
# Ajusta este valor para mostrar más o menos detecciones
threshold = 0.1
# Ejecutar la detección de objetos
run_detection(candidates, image_urls, threshold=threshold)
¡El modelo pudo detectar esta abeja con un 74 % de confianza! Ahora probemos una imagen con varios animales. En este caso, analizaremos imágenes de peces.
# Objetos candidatos a detectar
# Las etiquetas en inglés suelen producir mejores resultados con este modelo
candidates = [
"fish"
]
# URL de las imágenes que se analizarán; puedes agregar varias
image_urls = [
"https://img.freepik.com/free-photo/koi-fish-swimming-pond_23-2152023678.jpg?semt=ais_hybrid&w=740&q=80",
"https://images.pexels.com/photos/33855858/pexels-photo-33855858/free-photo-of-vibrant-goldfish-swimming-in-aquarium.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"https://inaturalist-open-data.s3.amazonaws.com/photos/639441608/large.jpg"
]
# Ajusta este valor para mostrar más o menos detecciones
threshold = 0.2
# Ejecutar la detección de objetos
run_detection(candidates, image_urls, threshold=threshold)
Exploremos otro ejemplo. ¿Podemos encontrar palmeras y excluir otros tipos de árboles?
# Objetos candidatos a detectar
# Las etiquetas en inglés suelen producir mejores resultados con este modelo
candidates = [
"palm tree"
]
# URL de las imágenes que se analizarán; puedes agregar varias
image_urls = [
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTGCFHamuK-Ojb5oQ-M4wj_zV0ZrI7ysQOF2A&s",
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS2B5bF_UoqzH6f3QnBMtNUoUk7WfelIiSIAQ&s",
"https://img.freepik.com/free-photo/grove-summer_1398-333.jpg"
]
# Ajusta este valor para mostrar más o menos detecciones
threshold = 0.1
run_detection(candidates, image_urls, threshold=threshold)
Para probar tu propio ejemplo, utiliza el siguiente código:
# Objetos candidatos a detectar
# Escribe las etiquetas en inglés para obtener mejores resultados
candidates = [
"object description in English"
]
# Puedes incluir URL de imágenes o nombres de archivos subidos
image_urls = [
"URL_DE_LA_IMAGEN",
"URL_DE_LA_IMAGEN",
# También puedes subir una imagen haciendo clic en el ícono de carpeta
# ubicado a la izquierda en Google Colab. Después, incluye aquí el
# nombre exacto del archivo que subiste.
"nombre_del_archivo_subido.png"
]
# Ajusta este valor para mostrar más o menos detecciones
# Un umbral más cercano a 1 muestra menos detecciones, pero con mayor confianza
threshold = 0.1
run_detection(candidates, image_urls, threshold=threshold)