Cómo aislar objetos segmentados con Ultralytics YOLO#
La segmentación de instancias produce una máscara precisa a nivel de píxel para cada objeto detectado, lo que significa que puedes extraer cada objeto de una imagen de forma independiente. Esta guía te muestra cómo convertir los resultados de segmentación de Ultralytics YOLO en objetos aislados utilizando el modo Predicción y OpenCV, ya sea con un fondo negro sólido o uno transparente para guardarlo 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 abre una serie de flujos de trabajo posteriores:
- Eliminación de 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 enfocado para que los pasos posteriores como OCR, análisis de color o medición vean solo el objeto, no la escena circundante.
- Exportación a PNG transparente para componer objetos sobre nuevos fondos.
El procedimiento funciona con cualquier modelo de segmentación de Ultralytics YOLO y sigue cuatro etapas: ejecutar la inferencia → extraer cada contorno → aislar el objeto → guardar el resultado.
Ejecutar la inferencia de segmentación#
Instala las bibliotecas necesarias, luego carga un modelo de segmentación (el sufijo -seg, requerido para producir máscaras) y ejecuta la predicción en 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")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 cual resulta útil para probar rápidamente el flujo de trabajo.
Extraer contornos de objetos#
Cada elemento en results corresponde a una imagen, y al iterar sobre un resultado se obtiene una detección a la vez. Para cada detección, copia la imagen original, lee la etiqueta de clase y dibuja el contorno de la máscara del objeto en una máscara binaria en blanco. La región blanca de esta máscara marca exactamente qué píxeles pertenecen al objeto.
Los fragmentos de esta sección y la siguiente se ejecutan dentro del bucle de detección que aparece a continuación; el script completo y listo para copiar se encuentra en Ejemplo completo.
{ width="240", align="right" }
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)c.masks.xy[0]devuelve el contorno de la máscara como coordenadas de puntos(x, y)para el objeto en este resultado de detección única..astype(np.int32)convierte los puntos defloat32, los cualesdrawContours()de OpenCV no acepta..reshape(-1, 1, 2)reorganiza los puntos en el diseño[N, 1, 2]que esperadrawContours(), dondeNes 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 delimitado.
Aislar el objeto#
Con la máscara binaria lista, combínala con la imagen original. Hay dos estilos comunes, dependiendo de lo que quieras que sea el fondo:
Convierte la máscara a tres canales y mantén solo los píxeles que se superponen con el objeto. Todo lo que esté 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)Para mantener solo la región del objeto en lugar de la imagen de tamaño completo, recórtala a la caja delimitadora 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]Eso viene integrado. Pasa save_crop=True a predict() y Ultralytics guarda los recortes de cuadros delimitadores automáticamente, sin necesidad de aplicar máscaras.
Guardar el resultado (opcional)#
Lo que hagas con cada objeto aislado depende de ti. Un siguiente paso común es escribirlo en el disco para su uso posterior:
# Save the isolated object to file
cv2.imwrite(f"{img_name}_{label}-{ci}.png", isolated)Aquí img_name es la raíz de la imagen de origen, label es el nombre de la clase y ci es el índice de detección, por lo que múltiples instancias de la misma clase obtienen nombres de archivo únicos. Intercambia isolated por iso_crop si aplicaste el recorte opcional anterior.
Ejemplo completo#
El script a continuación combina cada paso en un único bloque ejecutable. Utiliza un fondo negro por defecto; cambia la única línea marcada a np.dstack([img, b_mask]) para obtener un PNG transparente en su lugar:
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])Para uso repetido, envuelve el cuerpo del bucle en una función para que puedas llamarla en muchas imágenes.
Conclusión#
Ahora dispones de un procedimiento completo para aislar objetos segmentados con Ultralytics YOLO: ejecuta la inferencia, construye una máscara binaria a partir de cada contorno, extrae el objeto sobre un fondo negro o transparente y, opcionalmente, recórtalo según su cuadro delimitador. Explora la documentación completa de la tarea de segmentación y del modo Predicción para adaptar el flujo de trabajo a tus propias clases.
FAQ#
Carga un modelo de segmentación, ejecuta la inferencia, construye 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 connp.dstack([img, b_mask]). Ambos se muestran en Aislar el objeto.Lee las coordenadas de la caja delimitadora 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 Predicción.
Ultralytics YOLO proporciona segmentación de instancias rápida y en tiempo real con generación precisa de máscaras y cajas delimitadoras, además de una API de Python sencilla que convierte los resultados de inferencia en objetos aislados con unas pocas líneas de código de OpenCV.
Sí. Utiliza el argumento
save_cropenpredict()para guardar recortes de cuadros delimitadores con su fondo original:results = model.predict(source="path/to/your/image.jpg", save_crop=True)Lee más en la sección de argumentos de inferencia del modo Predicción.