Ultralytics YOLO27:

Cómo aislar objetos segmentados con Ultralytics YOLO#

La segmentación de instancias genera una máscara precisa a nivel de píxel para cada objeto detectado, lo que significa que puedes extraer cada objeto de una imagen por separado. Esta guía te muestra cómo convertir los resultados de segmentación de Ultralytics YOLO en objetos aislados mediante el modo de predicción y OpenCV, con un fondo negro uniforme o transparente para guardarlos como PNG.



Watch: How to Remove Background and Isolate Objects with Ultralytics YOLO Segmentation & OpenCV in Python 🚀

¿Por qué aislar objetos segmentados?#

Extraer objetos individuales de una imagen permite realizar diversos flujos de trabajo posteriores:

  • Eliminación del fondo para fotografías de productos, catálogos o edición creativa.
  • Recortes por objeto para crear conjuntos de datos de clasificación a partir de tus detecciones.
  • Procesamiento centrado para que los pasos posteriores, como el OCR, el análisis de color o la medición, vean solo el objeto y no la escena circundante.
  • Exportación a PNG transparente para combinar objetos con fondos nuevos.

La receta funciona con cualquier modelo de segmentación de Ultralytics YOLO y sigue cuatro fases: ejecutar la inferenciaextraer cada contornoaislar el objetoguardar el resultado.

Ejecutar la inferencia de segmentación#

Instala las bibliotecas necesarias, carga un modelo de segmentación (el sufijo -seg, necesario para generar máscaras) y ejecuta la predicción sobre tu imagen de origen:

from ultralytics import YOLO

# Load a segmentation model
model = YOLO("yolo26n-seg.pt")

# Run inference on a source
results = model.predict(source="path/to/image.jpg")
¿No tienes una imagen de origen? YOLO utiliza las imágenes de ejemplo incluidas

Si llamas a model.predict() sin un source, Ultralytics recurre a las imágenes de ejemplo incluidas con el paquete (bus.jpg y zidane.jpg), lo que resulta práctico para probar rápidamente el flujo de trabajo.

Extraer los contornos de los objetos#

Cada elemento de results corresponde a una imagen, y al iterar sobre un resultado se obtiene una detección cada vez. Para cada detección, copia la imagen original, lee la etiqueta de clase y dibuja el contorno de la máscara del objeto sobre una máscara binaria vacía. La región blanca de esta máscara indica exactamente qué píxeles pertenecen al objeto.

Los fragmentos de código de esta sección y de la siguiente se ejecutan dentro del bucle de detección que aparece abajo; el script completo, listo para copiar y pegar, está en Ejemplo completo.

Binary Mask Image
from pathlib import Path

import cv2
import numpy as np

for r in results:
    img = np.copy(r.orig_img)
    img_name = Path(r.path).stem  # source image base-name

    # Iterate each detected object in the image
    for ci, c in enumerate(r):
        label = c.names[c.boxes.cls.tolist().pop()]  # class name

        # Build a binary mask and draw the object contour onto it
        b_mask = np.zeros(img.shape[:2], np.uint8)
        contour = c.masks.xy[0].astype(np.int32).reshape(-1, 1, 2)
        cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
¿Qué hace `c.masks.xy[0].astype(np.int32).reshape(-1, 1, 2)`?
  • c.masks.xy[0] devuelve el contorno de la máscara como coordenadas de puntos (x, y) del objeto en este resultado de detección única.
  • .astype(np.int32) convierte los puntos de float32, que drawContours() de OpenCV no acepta.
  • .reshape(-1, 1, 2) cambia la forma de los puntos al formato [N, 1, 2] que espera drawContours(), donde N es el número de puntos del contorno.

Pasar [contour] con el índice -1 dibuja todos los puntos del contorno proporcionado, y cv2.FILLED rellena de blanco cada píxel encerrado.

Aislar el objeto#

Con la máscara binaria preparada, combínala con la imagen original. Hay dos estilos habituales, según cómo quieras que sea el fondo:

Elige un estilo de aislamiento

Convierte la máscara a tres canales y conserva solo los píxeles que se solapan con el objeto. Todo lo que queda fuera del contorno se vuelve negro:

# Isolate object with a black background
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
isolated = cv2.bitwise_and(mask3ch, img)
Example Full size Isolated Object Image Black Background
Full-size object on a black background
Recortar al cuadro delimitador

Para conservar solo la región del objeto en lugar de la imagen a tamaño completo, recórtala al cuadro delimitador de la detección:

# Bounding box coordinates
x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
# Crop the isolated image to the object region
iso_crop = isolated[y1:y2, x1:x2]
Example Crop Isolated Object Image Black Background
Object cropped to its bounding box
¿Necesitas el recorte con su fondo original?

Esta función está integrada. Pasa save_crop=True a predict() y Ultralytics guardará automáticamente los recortes del cuadro delimitador, sin necesidad de aplicar máscaras.

Guardar el resultado (opcional)#

Tú decides qué hacer con cada objeto aislado. Un paso posterior habitual es escribirlo en el disco para utilizarlo más adelante:

# Save the isolated object to file
cv2.imwrite(f"{img_name}_{label}-{ci}.png", isolated)

Aquí, img_name es el nombre base de la imagen de origen, label es el nombre de la clase y ci es el índice de la detección, por lo que las distintas instancias de una misma clase obtienen nombres de archivo únicos. Sustituye isolated por iso_crop si has aplicado el recorte opcional anterior.

Ejemplo completo#

El siguiente script combina todos los pasos en un único bloque ejecutable. Utiliza un fondo negro de forma predeterminada; cambia la única línea marcada a np.dstack([img, b_mask]) para obtener un PNG transparente:

from pathlib import Path

import cv2
import numpy as np

from ultralytics import YOLO

model = YOLO("yolo26n-seg.pt")
results = model.predict(source="path/to/image.jpg")

for r in results:
    img = np.copy(r.orig_img)
    img_name = Path(r.path).stem

    for ci, c in enumerate(r):
        label = c.names[c.boxes.cls.tolist().pop()]

        # Build a binary mask from the object contour
        b_mask = np.zeros(img.shape[:2], np.uint8)
        contour = c.masks.xy[0].astype(np.int32).reshape(-1, 1, 2)
        cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)

        # Isolate the object (black background)
        mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
        isolated = cv2.bitwise_and(mask3ch, img)  # transparent PNG: isolated = np.dstack([img, b_mask])

        # Save or add your custom post-processing here
        cv2.imwrite(f"{img_name}_{label}-{ci}.png", isolated)

        # Optional: crop to the bounding box before saving
        # x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
        # cv2.imwrite(f"{img_name}_{label}-{ci}.png", isolated[y1:y2, x1:x2])

Si vas a utilizarlo repetidamente, encapsula el cuerpo del bucle en una función para poder llamarla con muchas imágenes.

Conclusión#

Ya tienes una receta completa para aislar objetos segmentados con Ultralytics YOLO: ejecuta la inferencia, crea una máscara binaria a partir de cada contorno, extrae el objeto sobre un fondo negro o transparente y, de forma opcional, recórtalo a su cuadro delimitador. Consulta la documentación completa de Tarea de segmentación y del modo de predicción para adaptar el flujo de trabajo a tus propias clases.

Preguntas frecuentes#

  • Carga un modelo de segmentación, ejecuta la inferencia, crea una máscara binaria a partir del contorno de cada detección y combínala con la imagen original:

    import cv2
    import numpy as np
    
    from ultralytics import YOLO
    
    model = YOLO("yolo26n-seg.pt")
    results = model.predict(source="path/to/your/image.jpg")
    
    img = np.copy(results[0].orig_img)
    b_mask = np.zeros(img.shape[:2], np.uint8)
    contour = results[0].masks.xy[0].astype(np.int32).reshape(-1, 1, 2)
    cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
    
    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    isolated = cv2.bitwise_and(mask3ch, img)

    Consulta el Ejemplo completo para ver el bucle completo por detección.

  • Hay dos estilos principales. Para un fondo negro, convierte la máscara a tres canales y utiliza cv2.bitwise_and(). Para un fondo transparente (al guardar como PNG), apila la máscara como un cuarto canal alfa con np.dstack([img, b_mask]). Ambos se muestran en Aislar el objeto.

  • Lee las coordenadas del cuadro delimitador de la detección y recorta la imagen aislada:

    x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32)
    iso_crop = isolated[y1:y2, x1:x2]

    Obtén más información sobre los resultados de los cuadros delimitadores en la documentación del modo de predicción.

  • Ultralytics YOLO proporciona una segmentación de instancias rápida y en tiempo real, con una generación precisa de máscaras y cuadros delimitadores, además de una API sencilla de Python que convierte los resultados de la inferencia en objetos aislados con unas pocas líneas de código de OpenCV.

  • Sí. Utiliza el argumento save_crop en predict() para guardar recortes del cuadro delimitador con su fondo original:

    results = model.predict(source="path/to/your/image.jpg", save_crop=True)

    Obtén más información en la sección Argumentos de inferencia del modo de predicción.

Comentarios