Ir al contenido

Aislar objetos de segmentación

Después de realizar la Tarea Segmento, a veces es conveniente extraer los objetos aislados de los resultados de la inferencia. Esta guía proporciona una receta genérica sobre cómo lograrlo utilizando elmodo Predict de Ultralytics .

Ejemplo de segmentación de objetos aislados

Recorrido por las recetas

  1. Consulte la secciónUltralytics Quickstart Installation para obtener información sobre la instalación de las bibliotecas necesarias.


  2. Cargar un modelo y ejecutar predict() en una fuente.

    from ultralytics import YOLO
    
    # Load a model
    model = YOLO("yolo11n-seg.pt")
    
    # Run inference
    results = model.predict()
    

    ¿No hay argumentos de predicción?

    Si no se especifica 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 más información sobre los modelos de segmentación, visite la página Segmento Tarea página. Para saber más sobre predict() véase Modo Predecir de la Documentación.


  3. 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ón class-label se recuperan para su uso posterior (opcional).

    from pathlib import Path
    
    import numpy as np
    
    #  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):
            #  Get detection class name
            label = c.names[c.boxes.cls.tolist().pop()]
    
    Bucle For

    Una sola imagen sólo iterará el primer bucle una vez. Una sola imagen con una sola detección iterará cada bucle una sola vez.


  4. Empiece por generar una máscara binaria a partir de la imagen de origen y, a continuación, dibuje un contorno relleno sobre la máscara. Esto permitirá aislar el objeto de las demás partes de la imagen. Un ejemplo de bus.jpg para uno de los person se muestra a la derecha.

    Imagen de máscara binaria

    import cv2
    
    # Create binary mask
    b_mask = np.zeros(img.shape[:2], np.uint8)
    
    #  Extract contour result
    contour = c.masks.xy.pop()
    #  Changing the type
    contour = contour.astype(np.int32)
    #  Reshaping
    contour = contour.reshape(-1, 1, 2)
    
    
    # Draw contour onto mask
    _ = cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
    

    Ampliar para entender lo que ocurre al definir el contour variable.

    • c.masks.xy :: Proporciona las coordenadas de los puntos de contorno de la máscara en el formato (x, y). Para más información, consulte el Sección Máscaras del modo Predecir.

    • .pop() :: Como masks.xy es una lista que contiene un único elemento, este elemento se extrae utilizando la función pop() método.

    • .astype(np.int32) :: Utilización de masks.xy devolverá con un tipo de datos de float32pero esto no será compatible con el OpenCV drawContours() esto cambiará el tipo de datos a int32 por compatibilidad.

    • .reshape(-1, 1, 2) :: Reformatea los datos en la forma requerida de [N, 1, 2] donde N es el número de puntos de contorno, con cada punto representado por una única entrada 1y la entrada se compone de 2 valores. En -1 denota que el número de valores a lo largo de esta dimensión es flexible.

    Ampliar para una explicación del drawContours() configuración.

    • Encapsulando el contour variable entre corchetes, [contour]generó eficazmente la máscara de contorno deseada.

    • El valor -1 especificado para el drawContours() indica a la función que dibuje todos los contornos presentes en la imagen.

    • En tuple (255, 255, 255) representa el color blanco, que es el color deseado para dibujar el contorno en esta máscara binaria.

    • La adición de cv2.FILLED coloreará todos los píxeles encerrados por el límite del contorno de la misma manera, en este caso, todos los píxeles encerrados serán blancos.

    • Véase Documentación de OpenCV en drawContours() para más información.


  5. A continuación hay 2 opciones para avanzar con la imagen a partir de 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?
    • En primer lugar, la máscara binaria se convierte de una imagen de un solo canal a una imagen de tres canales. Esta conversión es necesaria para el paso siguiente, en el que se combinan la máscara y la imagen original. Ambas imágenes deben tener el mismo número de canales para que sean compatibles con la operación de mezcla.

    • La imagen original y la máscara binaria de tres canales se fusionan mediante la función OpenCV bitwise_and(). Esta operación conserva sólo valores de píxeles superiores a cero (> 0) de ambas imágenes. Dado que los píxeles de la máscara son mayores que cero (> 0) sólo dentro de la región del contorno, los píxeles restantes de la imagen original son los que se solapan con el contorno.

    Aislar con píxeles negros: Subopciones

    Imagen a tamaño completo

    No se requieren pasos adicionales si se mantiene la imagen a tamaño completo.

    Ejemplo Imagen de objeto aislado a tamaño completo Fondo negro
    Ejemplo de salida a tamaño completo

    Objeto recortado Imagen

    Pasos adicionales necesarios para recortar la imagen de modo que sólo incluya la región del objeto.

    Ejemplo Recortar Imagen Objeto Aislado Fondo Negro

    #  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]
    

    ¿Qué hace este código?
    • En c.boxes.xyxy.cpu().numpy() recupera los cuadros delimitadores como una matriz NumPy en el archivo xyxy donde xmin, ymin, xmaxy ymax representan las coordenadas del rectángulo del cuadro delimitador. Véase Sección de cajas del modo Predecir para más detalles.

    • En squeeze() elimina cualquier dimensión innecesaria de la matriz NumPy, asegurándose de que tiene la forma esperada.

    • Conversión de los valores de las coordenadas mediante .astype(np.int32) cambia el tipo de datos de las coordenadas de la caja de float32 a int32por lo que son compatibles con el recorte de imágenes mediante cortes de índice.

    • Por último, la región del cuadro delimitador se recorta de la imagen mediante el corte de índice. Los límites se definen mediante los parámetros [ymin:ymax, xmin:xmax] coordenadas del cuadro delimitador de la detección.

    # Isolate object with transparent background (when saved as PNG)
    isolated = np.dstack([img, b_mask])
    
    ¿Cómo funciona?
    • Uso de NumPy dstack() (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 una PNG archivo.

    Aislar con píxeles transparentes: Subopciones

    Imagen a tamaño completo

    No se requieren pasos adicionales si se mantiene la imagen a tamaño completo.

    Ejemplo a tamaño completo Imagen de objeto aislado sin fondo
    Ejemplo a tamaño completo + fondo transparente

    Objeto recortado Imagen

    Pasos adicionales necesarios para recortar la imagen de modo que sólo incluya la región del objeto.

    Ejemplo Recortar Imagen Objeto Aislado Sin Fondo

    #  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]
    

    ¿Qué hace este código?
    • Al utilizar c.boxes.xyxy.cpu().numpy()las cajas delimitadoras se devuelven como una matriz NumPy, utilizando la función xyxy formato de coordenadas de caja, que corresponden a los puntos xmin, ymin, xmax, ymax para el cuadro delimitador (rectángulo), véase Sección de cajas del modo Predecir para más información.

    • Añadir squeeze() garantiza que se elimine cualquier dimensión extraña de la matriz NumPy.

    • Conversión de los valores de las coordenadas mediante .astype(np.int32) cambia el tipo de datos de las coordenadas de la caja de float32 a int32 que será compatible al recortar la imagen utilizando cortes de índice.

    • Por último, la región de la imagen para el cuadro delimitador se recorta mediante el corte de índice, en el que los límites se establecen mediante la función [ymin:ymax, xmin:xmax] coordenadas del cuadro delimitador de la detección.

    ¿Y si quiero el objeto recortado incluyendo el fondo?

    Se trata de una función integrada en la biblioteca Ultralytics . Consulte la página save_crop argumento para Argumentos de inferencia del modo Predecir para más detalles.


  6. Como desarrollador, usted decide qué hacer a continuación. Se muestra un ejemplo básico de un posible paso siguiente (guardar la imagen en un archivo para su uso futuro).

    • NOTA: este paso es opcional y puede omitirse si no es necesario para su caso de uso específico.
    Ejemplo 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, y ci es el índice del detección de objetos (en caso de varias 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 único 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 bloque de código for-loops, pero eso 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")  
res = m.predict()  

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

    # Iterate each object contour 
    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 
        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 

PREGUNTAS FRECUENTES

¿Cómo aislar objetos utilizando Ultralytics YOLO11 para tareas de segmentación?

Para aislar objetos utilizando Ultralytics YOLO11 , siga estos pasos:

  1. Cargar el modelo y ejecutar la inferencia:

    from ultralytics import YOLO
    
    model = YOLO("yolo11n-seg.pt")
    results = model.predict(source="path/to/your/image.jpg")
    
  2. 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)
    
  3. Aísla el objeto utilizando 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 Predecir y la Tarea Segmento para obtener más información.

¿Qué opciones hay para guardar los objetos aislados después de la segmentación?

Ultralytics YOLO11 ofrece dos opciones principales para guardar objetos aislados:

  1. Con fondo negro:

    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    isolated = cv2.bitwise_and(mask3ch, img)
    
  2. Con fondo transparente:

    isolated = np.dstack([img, b_mask])
    

Para más detalles, visite la sección Modo Predicción.

¿Cómo puedo recortar objetos aislados a sus cuadros delimitadores utilizando Ultralytics YOLO11 ?

Para recortar objetos aislados a sus cuadros delimitadores:

  1. Recupera las coordenadas del cuadro delimitador:

    x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32)
    
  2. Recorta 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 Predecir.

¿Por qué debería utilizar Ultralytics YOLO11 para aislar objetos en tareas de segmentación?

Ultralytics YOLO11 proporciona:

  • Detección y segmentación de objetos a alta velocidad y en tiempo real.
  • Generación precisa de recuadros delimitadores y máscaras para aislar con precisión los objetos.
  • Documentación exhaustiva y API fácil de usar para un desarrollo eficaz.

Explore las ventajas de utilizar YOLO en la documentación Tarea de segmento.

¿Puedo guardar objetos aislados, incluido el fondo, utilizando Ultralytics YOLO11 ?

Sí, es una función integrada en Ultralytics YOLO11 . Utilice la función save_crop en el predict() método. Por ejemplo:

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

Más información save_crop en el Argumentos de inferencia del modo Predecir sección.

Creado hace 1 año ✏️ Actualizado hace 5 meses

Comentarios