Logotipo de Zephyrnet

Segmentación de instancias con YOLOv7 en Python

Fecha:

Introducción

La detección de objetos es un campo amplio en la visión por computadora y una de las aplicaciones más importantes de la visión por computadora "en la naturaleza". De él, se extrajo la segmentación de instancias, y tiene la tarea de hacer que los modelos predigan no solo la etiqueta y el cuadro delimitador de un objeto, sino también el "área" que cubre, clasificando cada píxel que pertenece a ese objeto.

La segmentación semántica clasifica todos los píxeles de una imagen según su semántico etiqueta (coche, acera, edificio). La segmentación de instancias clasifica todos los píxeles de cada objeto detectado individualmente, y Coche1 se diferencia de Coche2.

Conceptualmente, son similares, pero la segmentación de instancias combina la segmentación semántica y la detección de objetos. Afortunadamente, la detección de objetos, la segmentación semántica y la segmentación de instancias por extensión se pueden realizar con un back-end común, con diferentes jefes de la red, ya que se les asigna una tarea conceptualmente similar y, por lo tanto, comparten representaciones computacionales de ese conocimiento.

La detección de objetos, la segmentación semántica, la segmentación de instancias y la detección de puntos clave no están tan estandarizados como la clasificación de imágenes, principalmente porque la mayoría de los nuevos desarrollos suelen realizarlos investigadores, mantenedores y desarrolladores individuales, en lugar de grandes bibliotecas y marcos. Es difícil empaquetar los scripts de utilidad necesarios en un marco como TensorFlow o PyTorch y mantener las pautas de la API que guiaron el desarrollo hasta el momento.

Afortunadamente para las masas, Ultralytics ha desarrollado una API de detección de objetos simple, muy poderosa y hermosa en torno a su YOLOv5 que otros equipos de investigación y desarrollo han ampliado a versiones más nuevas, como YOLOv7.

En esta breve guía, realizaremos la segmentación de instancias en Python, con YOLOv7 de última generación.

Segmentación de instancias y YOLO

YOLO (Solo se mira una vez) es una metodología, así como una familia de modelos construidos para la detección de objetos. Desde el inicio en 2015, YOLOv1, YOLOv2 (YOLO9000) y YOLOv3 han sido propuestos por los mismos autores, y la comunidad de aprendizaje profundo continuó con avances de código abierto en los años siguientes.

YOLOv5 de ultralíticos es un repositorio masivo y la primera implementación a nivel de producción de YOLO en PyTorch, que ha tenido un uso importante en la industria. La implementación de PyTorch lo hizo más accesible que nunca, lo que generalmente se hacía en C++, pero la razón principal por la que se hizo tan popular es por la API maravillosamente simple y poderosa construida a su alrededor, que permite que cualquier persona pueda ejecutar unas pocas líneas de Python. código capaz de construir detectores de objetos.

YOLOv5 se ha convertido en un elemento tan básico que la mayoría de los repositorios que pretenden avanzar en el método YOLO lo utilizan como base y ofrecen una API similar heredada de Ultralytics. YOLOR (Solo Aprendes Una Representación) hizo exactamente esto, y los mismos autores construyeron YOLOv7 sobre YOLOR.

YOLOv7 es el primer modelo de YOLO que se envía con cabezales de modelos nuevos, lo que permite puntos clave, segmentación de instancias y detección de objetos, lo cual fue una adición muy sensata. Con suerte, en el futuro, veremos un número creciente de modelos basados ​​en YOLO que ofrecen capacidades similares listas para usar.

Esto hace que la segmentación de instancias y la detección de puntos clave sean más rápidas que nunca, con una arquitectura más simple que los detectores de dos etapas.

El modelo en sí se creó a través de cambios arquitectónicos, además de optimizar aspectos de la capacitación, denominados "bolsa de regalos", que aumentaron la precisión sin aumentar el costo de la inferencia.

Segmentación de instancias con YOLOv7

Una biblioteca estándar utilizada para la segmentación de instancias, la detección de objetos y la estimación de puntos clave en Python es Detectron2, creada por Meta AI.

La biblioteca ofrece varios métodos y clases convenientes para ayudar a visualizar los resultados de manera hermosa, pero la implementación subyacente para la detección es una máscara R-CNN. Se ha demostrado que YOLO supera a los modelos basados ​​en R-CNN en todos los ámbitos. El repositorio de YOLOv7 es compatible con Detectron2 y cumple con su API y sus herramientas de visualización, lo que facilita la ejecución de una segmentación de instancias rápida y precisa sin tener que aprender una nueva API. De hecho, puede cambiar la red troncal de Mask R-CNN y reemplazarla con YOLOv7.

Instalación de dependencias: YOLOv7 y Detectron2

Primero avancemos e instalemos las dependencias. Clonaremos el repositorio de GitHub para el proyecto YOLOv7 e instalaremos la última versión de Detectron2 a través de pip:

! git clone -b mask https://github.com/WongKinYiu/yolov7.git
! pip install pyyaml==5.1
! pip install 'git+https://github.com/facebookresearch/detectron2.git'

Detectron2 requiere pyyaml también. Para garantizar la compatibilidad, también querrá especificar la ejecución torch Versión:

! pip install torch==1.10.1+cu111 torchvision==0.11.2+cu111 torchaudio==0.10.1 -f https://download.pytorch.org/whl/torch_stable.html

La rama principal de YOLOv7 no admite la segmentación de instancias, ya que depende de un proyecto de terceros. sin embargo, el mask branch se hizo exactamente para este soporte, por lo que estamos instalando el mask rama del proyecto. Finalmente, querrá descargar los pesos pre-entrenados para el modelo de segmentación de instancias ya sea manualmente o con:

%cd yolov7
! curl -L https://github.com/WongKinYiu/yolov7/releases/download/v0.1/yolov7-mask.pt -o yolov7-mask.pt

Primero nos mudamos a la yolov7 (el directorio descargado que contiene el proyecto) y luego descargó el archivo de pesos allí. Con eso, ¡nuestras dependencias están configuradas! Importemos los paquetes y las clases que usaremos:

import matplotlib.pyplot as plt
import torch
import cv2
import yaml
from torchvision import transforms
import numpy as np

from utils.datasets import letterbox
from utils.general import non_max_suppression_mask_conf

from detectron2.modeling.poolers import ROIPooler
from detectron2.structures import Boxes
from detectron2.utils.memory import retry_if_cuda_oom
from detectron2.layers import paste_masks_in_image

Inferencia de segmentación de instancias con YOLOv7

Primero echemos un vistazo a la imagen que vamos a segmentar:

street_img = cv2.imread('../street.png')
street_img = cv2.cvtColor(street_img, cv2.COLOR_BGR2RGB)

fig = plt.figure(figsize=(12, 6))
plt.imshow(street_img)

¡Es una captura de pantalla de la vista en vivo de Google Maps! Dado que el modelo no está entrenado previamente en muchas clases, es probable que solo veamos segmentación semántica para clases como 'persona', 'coche', etc. sin clases de "grano fino" como 'semáforo'.

Ahora podemos empezar a cargar el modelo y prepararlo para la inferencia. los hyp.scratch.mask.yaml El archivo contiene configuraciones para hiperparámetros, por lo que inicialmente lo cargaremos, buscaremos el dispositivo activo (GPU o CPU) y cargaremos el modelo desde el archivo de pesos que acabamos de descargar:

Consulte nuestra guía práctica y práctica para aprender Git, con las mejores prácticas, los estándares aceptados por la industria y la hoja de trucos incluida. Deja de buscar en Google los comandos de Git y, de hecho, aprenden ella!

with open('data/hyp.scratch.mask.yaml') as f:
    hyp = yaml.load(f, Loader=yaml.FullLoader)

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

def load_model():
    model = torch.load('yolov7-mask.pt', map_location=device)['model']
    
    model.eval()

    if torch.cuda.is_available():
        
        
        model.half().to(device)
    return model

model = load_model()

A continuación, ¡creemos un método auxiliar para ejecutar la inferencia! Querremos que lea una imagen, la remodele y la rellene al tamaño de entrada esperado, aplique transformaciones, lo agrupa y lo pase al modelo:

def run_inference(url):
    image = cv2.imread(url) 
    
    image = letterbox(image, 640, stride=64, auto=True)[0] 
    
    image = transforms.ToTensor()(image) 
    
    image = image.half().to(device)
    
    image = image.unsqueeze(0) 
    output = model(image) 
    return output, image

output, image = run_inference('../street.png')

La función devuelve la salida del modelo, así como la propia imagen (cargada, rellenada y procesada). La salida es un diccionario:

output.keys()

Las predicciones que hizo el modelo están sin procesar; tendremos que pasarlas non_max_supression()y utilice el ROIPooler de Detectron2.

Nota: “Acumulación de retorno de la inversión” es la abreviatura de “Región de agrupación de intereses” y se utiliza para extraer pequeños mapas de características para tareas de detección y segmentación de objetos, en regiones que pueden contener objetos.

inf_out = output['test']
attn = output['attn']
bases = output['bases']
sem_output = output['sem']

bases = torch.cat([bases, sem_output], dim=1)
nb, _, height, width = image.shape
names = model.names
pooler_scale = model.pooler_scale

pooler = ROIPooler(output_size=hyp['mask_resolution'], 
                   scales=(pooler_scale,), 
                   sampling_ratio=1, 
                   pooler_type='ROIAlignV2', 
                   canonical_level=2)
                   

output, output_mask, _, _, _ = non_max_suppression_mask_conf(inf_out, 
                                                             attn, 
                                                             bases, 
                                                             pooler, 
                                                             hyp, 
                                                             conf_thres=0.25, 
                                                             iou_thres=0.65, 
                                                             merge=False, 
                                                             mask_iou=None)                 

Aquí, hemos obtenido las predicciones para los objetos y sus etiquetas en output y las máscaras que deben cubrir esos objetos en output_mask:

output[0].shape 
output_mask[0].shape 

El modelo encontró 30 instancias en la imagen, cada una con una etiqueta asociada. Creemos cajas para nuestras instancias con la ayuda de Detectron2 Boxes clase y condensar la pred_masks (que contienen una máscara booleana) en un conjunto de píxeles que podemos aplicar sobre la imagen original:

pred, pred_masks = output[0], output_mask[0]
base = bases[0]
bboxes = Boxes(pred[:, :4])

original_pred_masks = pred_masks.view(-1, 
                                      hyp['mask_resolution'], 
                                      hyp['mask_resolution'])

pred_masks = retry_if_cuda_oom(paste_masks_in_image)(original_pred_masks, 
                                                     bboxes, 
                                                     (height, width), 
                                                     threshold=0.5)
                                                     

pred_masks_np = pred_masks.detach().cpu().numpy()
pred_cls = pred[:, 5].detach().cpu().numpy()
pred_conf = pred[:, 4].detach().cpu().numpy()
nimg = image[0].permute(1, 2, 0) * 255
nimg = nimg.cpu().numpy().astype(np.uint8)
nimg = cv2.cvtColor(nimg, cv2.COLOR_RGB2BGR)
nbboxes = bboxes.tensor.detach().cpu().numpy().astype(np.int)

El original_pred_masks denota las máscaras predichas para la imagen original:

original_pred_masks.shape 

Y finalmente, podemos graficar los resultados con:

def plot_results(original_image, pred_img, pred_masks_np, nbboxes, pred_cls, pred_conf, plot_labels=True):
  for one_mask, bbox, cls, conf in zip(pred_masks_np, nbboxes, pred_cls, pred_conf):
    if conf < 0.25:
        continue
    color = [np.random.randint(255), np.random.randint(255), np.random.randint(255)]

    pred_img = pred_img.copy()
                             
    
    pred_img[one_mask] = pred_img[one_mask] * 0.5 + np.array(color, dtype=np.uint8) * 0.5
    
    pred_img = cv2.rectangle(pred_img, (bbox[0], bbox[1]), (bbox[2], bbox[3]), color, 2)

    if plot_labels:
      label = '%s %.3f' % (names[int(cls)], conf)
      t_size = cv2.getTextSize(label, 0, fontScale=0.1, thickness=1)[0]
      c2 = bbox[0] + t_size[0], bbox[1] - t_size[1] - 3
      pred_img = cv2.rectangle(pred_img, (bbox[0], bbox[1]), c2, color, -1, cv2.LINE_AA)
      pred_img = cv2.putText(pred_img, label, (bbox[0], bbox[1] - 2), 0, 0.5, [255, 255, 255], thickness=1, lineType=cv2.LINE_AA)  

  fig, ax = plt.subplots(1, 2, figsize=(pred_img.shape[0]/10, pred_img.shape[1]/10), dpi=150)

  original_image = np.moveaxis(image.cpu().numpy().squeeze(), 0, 2).astype('float32')
  original_image = cv2.cvtColor(original_image, cv2.COLOR_RGB2BGR)
  
  ax[0].imshow(original_image)
  ax[0].axis("off")
  ax[1].imshow(pred_img)
  ax[1].axis("off")

La imagen se copia, por lo que no aplicamos transformaciones a la imagen en el lugar, sino en una copia. Para cada píxel que coincida entre la imagen de entrada y las máscaras predichas, aplicamos un color con una opacidad de 0.5 y para cada objeto, dibujamos un cv2.Rectangle() que lo abarca desde los cuadros delimitadores (bbox). Si desea trazar etiquetas, para las cuales puede haber una superposición significativa, hay una plot_labels bandera en el plot_results() firma del método. Intentemos trazar la imagen con la que comenzamos a trabajar anteriormente con y sin etiquetas:

%matplotlib inline
plot_results(image, nimg, pred_masks_np, nbboxes, pred_cls, pred_conf, plot_labels=False)

%matplotlib inline
plot_results(image, nimg, pred_masks_np, nbboxes, pred_cls, pred_conf, plot_labels=True)

Hemos trazado ambas imágenes: la original y la imagen segmentada en un solo gráfico. Para una resolución más alta, ajuste el dpi (puntos por pulgada) argumento en el subplots() llame y trace solo la imagen con el mapa/etiquetas de segmentación previstos para ocupar la figura en su totalidad.

Yendo más lejos: aprendizaje profundo práctico para la visión por computadora

¿Tu naturaleza inquisitiva te hace querer ir más allá? Recomendamos revisar nuestro Curso: “Aprendizaje Profundo Práctico para Visión por Computador con Python”.

¿Otro curso de visión artificial?

No haremos clasificación de dígitos MNIST o moda MNIST. Cumplieron su parte hace mucho tiempo. Demasiados recursos de aprendizaje se centran en conjuntos de datos básicos y arquitecturas básicas antes de permitir que las arquitecturas avanzadas de caja negra carguen con la carga del rendimiento.

queremos centrarnos en desmitificación, sentido práctico, comprensión, intuición y proyectos reales. Querer aprender cómo ¿Tu puedes hacer la diferencia? Lo llevaremos en un viaje desde la forma en que nuestros cerebros procesan imágenes hasta escribir un clasificador de aprendizaje profundo de grado de investigación para el cáncer de mama y redes de aprendizaje profundo que "alucinan", enseñándole los principios y la teoría a través del trabajo práctico, equipándolo con el conocimientos y herramientas para convertirse en un experto en la aplicación del aprendizaje profundo para resolver la visión artificial.

¿Qué hay adentro?

  • Los primeros principios de la visión y cómo se puede enseñar a las computadoras a “ver”
  • Diferentes tareas y aplicaciones de la visión artificial
  • Las herramientas del oficio que facilitarán tu trabajo
  • Encontrar, crear y utilizar conjuntos de datos para la visión por computadora
  • La teoría y aplicación de las Redes Neuronales Convolucionales
  • Manejo de cambio de dominio, co-ocurrencia y otros sesgos en conjuntos de datos
  • Transfiera el aprendizaje y utilice el tiempo de capacitación y los recursos computacionales de otros para su beneficio
  • Construyendo y entrenando un clasificador de cáncer de mama de última generación
  • Cómo aplicar una buena dosis de escepticismo a las ideas principales y comprender las implicaciones de las técnicas ampliamente adoptadas
  • Visualización del "espacio conceptual" de ConvNet usando t-SNE y PCA
  • Casos prácticos de cómo las empresas utilizan técnicas de visión artificial para lograr mejores resultados
  • Evaluación adecuada del modelo, visualización del espacio latente e identificación de la atención del modelo.
  • Realizar investigaciones de dominio, procesar sus propios conjuntos de datos y establecer pruebas modelo
  • Arquitecturas de vanguardia, la progresión de las ideas, qué las hace únicas y cómo implementarlas
  • KerasCV: una biblioteca WIP para crear canalizaciones y modelos de última generación
  • Cómo analizar y leer documentos e implementarlos usted mismo
  • Selección de modelos en función de su aplicación
  • Creación de una canalización de aprendizaje automático de extremo a extremo
  • Panorama e intuición sobre la detección de objetos con Faster R-CNN, RetinaNets, SSD y YOLO
  • Instancia y segmentación semántica
  • Reconocimiento de objetos en tiempo real con YOLOv5
  • Capacitación de detectores de objetos YOLOv5
  • Trabajando con Transformers usando KerasNLP (biblioteca WIP de fuerza industrial)
  • Integrando Transformers con ConvNets para generar subtítulos de imágenes
  • sueño profundo
  • Optimización del modelo de Deep Learning para visión artificial
punto_img

café vc

café vc

Información más reciente

punto_img