Aislamiento de Objetos de Segmentación
Después de realizar la Tarea de Segmentación, a veces es deseable extraer los objetos aislados de los resultados de la inferencia. Esta guía proporciona una receta genérica sobre cómo lograr esto usando el Modo de Predicción de Ultralytics.
Recorrido de la receta
-
Consulta la sección de instalación rápida de Ultralytics para obtener una guía rápida sobre cómo instalar las bibliotecas necesarias.
-
Cargar un modelo y ejecutar
predict()
método en una fuente.from ultralytics import YOLO # Load a model model = YOLO("yolo11n-seg.pt") # Run inference results = model.predict()
¿Sin argumentos de predicción?
Sin especificar una fuente, se utilizarán las imágenes de ejemplo de la biblioteca:
'ultralytics/assets/bus.jpg' 'ultralytics/assets/zidane.jpg'
Esto es útil para realizar pruebas rápidas con el
predict()
método.Para obtener información adicional sobre los modelos de segmentación, visite la Tarea de segmentación página. Para obtener más información sobre
predict()
método, consulta Modo de Predicción sección de la Documentación.
-
Ahora itere sobre los resultados y los contornos. Para los flujos de trabajo que desean guardar una imagen en un archivo, la imagen de origen
base-name
y la detecciónclass-label
se recuperan para su uso posterior (opcional).from pathlib import Path import numpy as np # (2) Iterate detection results (helpful for multiple images) for r in res: img = np.copy(r.orig_img) img_name = Path(r.path).stem # source image base-name # Iterate each object contour (multiple detections) for ci, c in enumerate(r): # (1) Get detection class name label = c.names[c.boxes.cls.tolist().pop()]
- Para obtener más información sobre cómo trabajar con los resultados de la detección, consulte la Sección de Cajas para el Modo de Predicción.
- Para obtener más información sobre
predict()
resultados ver Trabajar con los resultados para el modo de predicción
Bucle For
Una sola imagen solo iterará el primer bucle una vez. Una sola imagen con una sola detección iterará cada bucle solo una vez.
-
Comience generando una máscara binaria a partir de la imagen de origen y luego dibuje un contorno relleno en la máscara. Esto permitirá aislar el objeto de las otras partes de la imagen. Un ejemplo de
bus.jpg
para uno de los detectadosperson
Los objetos de clase se muestran a la derecha.import cv2 # Create binary mask b_mask = np.zeros(img.shape[:2], np.uint8) # (1) Extract contour result contour = c.masks.xy.pop() # (2) Changing the type contour = contour.astype(np.int32) # (3) Reshaping contour = contour.reshape(-1, 1, 2) # Draw contour onto mask _ = cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
-
Para más información sobre
c.masks.xy
ver Sección de Máscaras del Modo de Predicción. -
Aquí los valores se convierten en
np.int32
para la compatibilidad condrawContours()
función de OpenCV. -
OpenCV
drawContours()
función espera que los contornos tengan una forma de[N, 1, 2]
expandir la sección a continuación para obtener más detalles.
Expandir para comprender lo que sucede al definir el
contour
variable.-
c.masks.xy
:: Proporciona las coordenadas de los puntos del contorno de la máscara en el formato(x, y)
. Para obtener más detalles, consulte el Sección de Máscaras del Modo de Predicción..pop()
:: Comomasks.xy
es una lista que contiene un solo elemento, este elemento se extrae usando elpop()
método. -.astype(np.int32)
:: Usandomasks.xy
devolverá un tipo de datos defloat32
, pero esto no será compatible con OpenCVdrawContours()
función, por lo que esto cambiará el tipo de datos aint32
para la compatibilidad. -.reshape(-1, 1, 2)
:: Reformatea los datos en la forma requerida de[N, 1, 2]
dondeN
es el número de puntos de contorno, con cada punto representado por una sola entrada1
, y la entrada se compone de2
valores. El-1
indica que el número de valores a lo largo de esta dimensión es flexible.Expandir para obtener una explicación del
drawContours()
configuración.- Encapsulando el
contour
variable entre corchetes,[contour]
, se encontró que genera eficazmente la máscara de contorno deseada durante las pruebas. - El valor-1
especificado para eldrawContours()
parámetro indica a la función que dibuje todos los contornos presentes en la imagen. - Eltuple
(255, 255, 255)
representa el color blanco, que es el color deseado para dibujar el contorno en esta máscara binaria. - La adición decv2.FILLED
coloreará todos los píxeles encerrados por el límite del contorno del mismo color, en este caso, todos los píxeles encerrados serán blancos. - Ver Documentación de OpenCV endrawContours()
para más información.
-
-
A continuación, hay 2 opciones sobre cómo avanzar con la imagen desde este punto y una opción posterior para cada una.
Opciones de aislamiento de objetos
Ejemplo
# Create 3-channel mask mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR) # Isolate object with binary mask isolated = cv2.bitwise_and(mask3ch, img)
¿Cómo funciona esto?
-
Primero, la máscara binaria se convierte primero de una imagen de un solo canal a una imagen de tres canales. Esta conversión es necesaria para el paso posterior donde se combinan la máscara y la imagen original. Ambas imágenes deben tener el mismo número de canales para ser compatibles con la operación de fusión.
-
La imagen original y la máscara binaria de tres canales se fusionan utilizando la función OpenCV
bitwise_and()
. Esta operación retiene solo valores de píxeles que son mayores que cero(> 0)
de ambas imágenes. Dado que los píxeles de la máscara son mayores que cero(> 0)
solo dentro de la región del contorno, los píxeles restantes de la imagen original son aquellos que se superponen con el contorno.
Aislar con píxeles negros: Sub-opciones
Imagen a tamaño completo
No se requieren pasos adicionales si se mantiene el tamaño completo de la imagen.
Ejemplo de salida a tamaño completo Imagen del objeto recortado
Pasos adicionales necesarios para recortar la imagen e incluir solo la región del objeto.
# (1) Bounding box coordinates x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32) # Crop image to object region iso_crop = isolated[y1:y2, x1:x2]
- Para obtener más información sobre los resultados del cuadro delimitador, consulta la Sección de Cajas del Modo de Predicción.
¿Qué hace este código?
-
El
c.boxes.xyxy.cpu().numpy()
call recupera los cuadros delimitadores como un array NumPy en elxyxy
formato, dondexmin
,ymin
,xmax
, yymax
representan las coordenadas del rectángulo delimitador. Ver Sección de cajas del modo de predicción para obtener más detalles. -
El
squeeze()
La operación elimina cualquier dimensión innecesaria de la matriz NumPy, asegurando que tenga la forma esperada. -
Conversión de los valores de las coordenadas utilizando
.astype(np.int32)
cambia el tipo de datos de las coordenadas del cuadro defloat32
a datosint32
, haciéndolos compatibles para el recorte de imágenes utilizando cortes de índice. -
Finalmente, la región del cuadro delimitador se recorta de la imagen utilizando el corte de índice. Los límites están definidos por el
[ymin:ymax, xmin:xmax]
coordenadas del cuadro delimitador de detección.
# Isolate object with transparent background (when saved as PNG) isolated = np.dstack([img, b_mask])
¿Cómo funciona esto?
- Usando el NumPy
dstack()
función (apilamiento de matrices a lo largo del eje de profundidad) junto con la máscara binaria generada, creará una imagen con cuatro canales. Esto permite que todos los píxeles fuera del contorno del objeto sean transparentes al guardar como unPNG
archivo.
Aislar con píxeles transparentes: Sub-opciones
Imagen a tamaño completo
No se requieren pasos adicionales si se mantiene el tamaño completo de la imagen.
Ejemplo de salida a tamaño completo + fondo transparente Imagen del objeto recortado
Pasos adicionales necesarios para recortar la imagen e incluir solo la región del objeto.
# (1) Bounding box coordinates x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32) # Crop image to object region iso_crop = isolated[y1:y2, x1:x2]
- Para obtener más información sobre los resultados del cuadro delimitador, consulta la Sección de Cajas del Modo de Predicción.
¿Qué hace este código?
-
Al usar
c.boxes.xyxy.cpu().numpy()
, los cuadros delimitadores se devuelven como un array de NumPy, utilizando elxyxy
formato de coordenadas del cuadro, que corresponden a los puntosxmin, ymin, xmax, ymax
para el cuadro delimitador (rectángulo), consulte Sección de cajas del modo de predicción para más información. -
Añadiendo
squeeze()
asegura que se eliminen las dimensiones extrañas del array NumPy. -
Conversión de los valores de las coordenadas utilizando
.astype(np.int32)
cambia el tipo de datos de las coordenadas del cuadro defloat32
a datosint32
que será compatible al recortar la imagen utilizando slices de índice. -
Finalmente, la región de la imagen para el cuadro delimitador se recorta utilizando el corte de índice, donde los límites se establecen utilizando el
[ymin:ymax, xmin:xmax]
coordenadas del cuadro delimitador de detección.
¿Qué pasa si quiero el objeto recortado incluyendo el fondo?
Esta es una característica incorporada para la biblioteca Ultralytics. Consulte el
save_crop
argumento para Argumentos de Inferencia del Modo de Predicción para obtener más detalles.
-
-
Lo que haga a continuación depende totalmente de usted como desarrollador. Se muestra un ejemplo básico de un posible siguiente paso (guardar la imagen en un archivo para su uso futuro).
- NOTA: este paso es opcional y se puede omitir si no es necesario para su caso de uso específico.
Ejemplo de paso final
# Save isolated object to file _ = cv2.imwrite(f"{img_name}_{label}-{ci}.png", iso_crop)
- En este ejemplo, el
img_name
es el nombre base del archivo de imagen de origen,label
es el nombre de la clase detectada, yci
es el índice del detección de objetos (en caso de múltiples instancias con el mismo nombre de clase).
Código de ejemplo completo
Aquí, todos los pasos de la sección anterior se combinan en un solo bloque de código. Para un uso repetido, sería óptimo definir una función para realizar algunos o todos los comandos contenidos en el for
-bucles, pero ese es un ejercicio que se deja al lector.
from pathlib import Path
import cv2
import numpy as np
from ultralytics import YOLO
m = YOLO("yolo11n-seg.pt") # (4)!
res = m.predict() # (3)!
# Iterate detection results (5)
for r in res:
img = np.copy(r.orig_img)
img_name = Path(r.path).stem
# Iterate each object contour (6)
for ci, c in enumerate(r):
label = c.names[c.boxes.cls.tolist().pop()]
b_mask = np.zeros(img.shape[:2], np.uint8)
# Create contour mask (1)
contour = c.masks.xy.pop().astype(np.int32).reshape(-1, 1, 2)
_ = cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
# Choose one:
# OPTION-1: Isolate object with black background
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
isolated = cv2.bitwise_and(mask3ch, img)
# OPTION-2: Isolate object with transparent background (when saved as PNG)
isolated = np.dstack([img, b_mask])
# OPTIONAL: detection crop (from either OPT1 or OPT2)
x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
iso_crop = isolated[y1:y2, x1:x2]
# TODO your actions go here (2)
- La línea que rellena
contour
se combina en una sola línea aquí, donde se dividió en varias líneas arriba. - ¡Lo que va aquí depende de ti!
- Consulta el Modo de predicción para obtener información adicional.
- Consulta la Tarea de segmentación para obtener más información.
- Obtenga más información sobre Cómo trabajar con los resultados
- Obtenga más información sobre los Resultados de la máscara de segmentación
Preguntas frecuentes
¿Cómo aíslo objetos usando Ultralytics YOLO11 para tareas de segmentación?
Para aislar objetos utilizando Ultralytics YOLO11, siga estos pasos:
-
Cargue el modelo y ejecute la inferencia:
from ultralytics import YOLO model = YOLO("yolo11n-seg.pt") results = model.predict(source="path/to/your/image.jpg")
-
Generar una máscara binaria y dibujar contornos:
import cv2 import numpy as np 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)
-
Aísle el objeto usando la máscara binaria:
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR) isolated = cv2.bitwise_and(mask3ch, img)
Consulte la guía sobre el Modo de Predicción y la Tarea de Segmentación para obtener más información.
¿Qué opciones están disponibles para guardar los objetos aislados después de la segmentación?
Ultralytics YOLO11 ofrece dos opciones principales para guardar objetos aislados:
-
Con un fondo negro:
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR) isolated = cv2.bitwise_and(mask3ch, img)
-
Con un fondo transparente:
isolated = np.dstack([img, b_mask])
Para obtener más detalles, visite la sección Modo de predicción.
¿Cómo puedo recortar objetos aislados a sus cuadros delimitadores usando Ultralytics YOLO11?
Para recortar objetos aislados a sus bounding boxes:
-
Recuperar las coordenadas del cuadro delimitador:
x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32)
-
Recortar la imagen aislada:
iso_crop = isolated[y1:y2, x1:x2]
Obtenga más información sobre los resultados del cuadro delimitador en la documentación del Modo de predicción.
¿Por qué debería usar Ultralytics YOLO11 para el aislamiento de objetos en tareas de segmentación?
Ultralytics YOLO11 proporciona:
- Detección y segmentación de objetos en tiempo real de alta velocidad.
- Generación precisa de cuadros delimitadores y máscaras para un aislamiento preciso de objetos.
- Documentación completa y API fácil de usar para un desarrollo eficiente.
Explora las ventajas de usar YOLO en la documentación de la tarea Segment.
¿Puedo guardar objetos aislados, incluido el fondo, utilizando Ultralytics YOLO11?
Sí, esta es una característica integrada en Ultralytics YOLO11. Utilice el save_crop
argumento en el predict()
método. Por ejemplo:
results = model.predict(source="path/to/your/image.jpg", save_crop=True)
Más información sobre save_crop
argumento en el Argumentos de Inferencia del Modo de Predicción sección.