Saltar al contenido

Utilidades sencillas

código con perspectiva

En ultralytics viene con una miríada de utilidades que pueden apoyar, mejorar y acelerar tus flujos de trabajo. Hay muchas más disponibles, pero aquí tienes algunas que serán útiles para la mayoría de los desarrolladores. También son un gran punto de referencia para utilizar cuando se aprende a programar.



Observa: Ultralytics Utilidades | Anotación automática, API del Explorador y Conversión de conjuntos de datos

Datos

YOLO Explorador de datos

YOLO Explorador se añadió en el 8.1.0 aniversario y es una potente herramienta que puedes utilizar para comprender mejor tu conjunto de datos. Una de las funciones clave que ofrece YOLO Explorer es la posibilidad de utilizar consultas de texto para encontrar instancias de objetos en tu conjunto de datos.

Autoetiquetado / Anotaciones

La anotación de conjuntos de datos es un proceso que consume muchos recursos y tiempo. Si tienes un modelo de detección de objetos YOLO entrenado en una cantidad razonable de datos, puedes utilizarlo y SAM para autoanotar datos adicionales (formato de segmentación).

from ultralytics.data.annotator import auto_annotate

auto_annotate(#(1)!
    data='path/to/new/data',
    det_model='yolov8n.pt',
    sam_model='mobile_sam.pt',
    device="cuda",
    output_dir="path/to/save_labels",
)
  1. Esta función no devuelve nada

  2. Consulta la sección de referencia para annotator.auto_annotate para más información sobre el funcionamiento de la función.

  3. Utilízalo en combinación con el función segments2boxes para generar también cuadros delimitadores de detección de objetos

Convierte COCO al formato YOLO

Se utiliza para convertir las anotaciones COCO JSON al formato adecuado YOLO . Para conjuntos de datos de detección de objetos (cuadro delimitador), use_segments y use_keypoints deben ser False

from ultralytics.data.converter import convert_coco

convert_coco(#(1)!
    '../datasets/coco/annotations/',
    use_segments=False, 
    use_keypoints=False,
    cls91to80=True,
)
  1. Esta función no devuelve nada

Para más información sobre el convert_coco función, visita la página de referencia

Obtener dimensiones del cuadro delimitador

from ultralytics.utils.plotting import Annotator
from ultralytics import YOLO
import cv2

model = YOLO('yolov8n.pt')  # Load pretrain or fine-tune model

# Process the image
source = cv2.imread('path/to/image.jpg')
results = model(source)

# Extract results
annotator = Annotator(source, example=model.names)

for box in results[0].boxes.xyxy.cpu():
    width, height, area = annotator.get_bbox_dimension(box)
    print("Bounding Box Width {}, Height {}, Area {}".format(
        width.item(), height.item(), area.item()))

Convertir cuadros delimitadores en segmentos

Con las x y w h datos del cuadro delimitador, conviértelos en segmentos utilizando la función yolo_bbox2segment función. Los archivos de imágenes y anotaciones deben organizarse así:

data
|__ images
    ├─ 001.jpg
    ├─ 002.jpg
    ├─ ..
    └─ NNN.jpg
|__ labels
    ├─ 001.txt
    ├─ 002.txt
    ├─ ..
    └─ NNN.txt
from ultralytics.data.converter import yolo_bbox2segment

yolo_bbox2segment(#(1)!
    im_dir="path/to/images",
    save_dir=None, # saved to "labels-segment" in images directory
    sam_model="sam_b.pt"
)
  1. Esta función no devuelve nada

Visita la página yolo_bbox2segment página de referencia para más información sobre la función.

Convertir segmentos en cuadros delimitadores

Si tienes un conjunto de datos que utiliza la función formato del conjunto de datos de segmentación puedes convertirlos fácilmente en cuadros delimitadores arriba-derecha (u horizontales) (x y w h formato) con esta función.

from ultralytics.utils.ops import segments2boxes

segments = np.array(
    [[805, 392, 797, 400, ..., 808, 714, 808, 392],
     [115, 398, 113, 400, ..., 150, 400, 149, 298],
     [267, 412, 265, 413, ..., 300, 413, 299, 412],
    ]
)

segments2boxes([s.reshape(-1,2) for s in segments])
>>> array([[ 741.66, 631.12, 133.31, 479.25],
           [ 146.81, 649.69, 185.62, 502.88],
           [ 281.81, 636.19, 118.12, 448.88]],
           dtype=float32) # xywh bounding boxes

Para entender cómo funciona esta función, visita la página de referencia

Utilidades

Compresión de imágenes

Comprime un único archivo de imagen a un tamaño reducido, conservando su relación de aspecto y calidad. Si la imagen de entrada es menor que la dimensión máxima, no se redimensionará.

from pathlib import Path
from ultralytics.data.utils import compress_one_image

for f in Path('path/to/dataset').rglob('*.jpg'):
    compress_one_image(f)#(1)!
  1. Esta función no devuelve nada

Dividir automáticamente el conjunto de datos

Dividir automáticamente un conjunto de datos en train/val/test y guarda las divisiones resultantes en autosplit_*.txt archivos. Esta función utilizará el muestreo aleatorio, que no se incluye cuando se utiliza fraction argumento para la formación.

from ultralytics.data.utils import autosplit

autosplit( #(1)!
    path="path/to/images",
    weights=(0.9, 0.1, 0.0), # (train, validation, test) fractional splits
    annotated_only=False     # split only images with annotation file when True
)
  1. Esta función no devuelve nada

Consulta la página Referencia para obtener más detalles sobre esta función.

Segmento-polígono a máscara binaria

Convierte un único polígono (en forma de lista) en una máscara binaria del tamaño de imagen especificado. Polígono en forma de [N, 2] con N como el número de (x, y) puntos que definen el contorno del polígono.

Advertencia

N debe siempre ser par.

import numpy as np
from ultralytics.data.utils import polygon2mask

imgsz = (1080, 810)
polygon = np.array(
    [805, 392, 797, 400, ..., 808, 714, 808, 392], # (238, 2)
)

mask = polygon2mask(
    imgsz,     # tuple
    [polygon], # input as list
    color=255, # 8-bit binary
    downsample_ratio=1
) 

Cajas delimitadoras

Cuadro delimitador (horizontal) Instancias

Para gestionar los datos de los recuadros delimitadores, la función Bboxes te ayudará a convertir entre formatos de coordenadas de cajas, escalar las dimensiones de las cajas, calcular áreas, incluir desplazamientos, ¡y mucho más!

from ultralytics.utils.instance import Bboxes

boxes = Bboxes(
    bboxes=np.array(
        [[  22.878,  231.27,  804.98,  756.83,],
         [  48.552,  398.56,  245.35,  902.71,],
         [  669.47,  392.19,  809.72,  877.04,],
         [  221.52,   405.8,  344.98,  857.54,],
         [       0,  550.53,   63.01,  873.44,],
         [  0.0584,  254.46,  32.561,  324.87,]]
    ),
    format="xyxy",
)

boxes.areas()
>>> array([ 4.1104e+05,       99216,       68000,       55772,       20347,      2288.5])
boxes.convert("xywh")
boxes.bboxes
>>> array(
    [[ 413.93, 494.05,  782.1, 525.56],
     [ 146.95, 650.63,  196.8, 504.15],
     [  739.6, 634.62, 140.25, 484.85],
     [ 283.25, 631.67, 123.46, 451.74],
     [ 31.505, 711.99,  63.01, 322.91],
     [  16.31, 289.67, 32.503,  70.41]]
)

Ver el Bboxes sección de referencia para ver más atributos y métodos disponibles.

Consejo

Se puede acceder a muchas de las siguientes funciones (y a otras más) utilizando la función Bboxes clase pero si prefieres trabajar con las funciones directamente, consulta las siguientes subsecciones sobre cómo importarlas de forma independiente.

Cajas de Escala

Al escalar una imagen hacia arriba o hacia abajo, las coordenadas correspondientes del cuadro delimitador pueden escalarse adecuadamente para que coincidan utilizando ultralytics.utils.ops.scale_boxes.

import cv2 as cv
import numpy as np
from ultralytics.utils.ops import scale_boxes

image = cv.imread("ultralytics/assets/bus.jpg")
*(h, w), c = image.shape
resized = cv.resize(image, None, (), fx=1.2, fy=1.2)
*(new_h, new_w), _ = resized.shape

xyxy_boxes = np.array(
    [[  22.878,  231.27,  804.98,  756.83,],
    [   48.552,  398.56,  245.35,  902.71,],
    [   669.47,  392.19,  809.72,  877.04,],
    [   221.52,   405.8,  344.98,  857.54,],
    [        0,  550.53,   63.01,  873.44,],
    [   0.0584,  254.46,  32.561,  324.87,]]
)

new_boxes = scale_boxes(
    img1_shape=(h, w),          # original image dimensions
    boxes=xyxy_boxes,           # boxes from original image
    img0_shape=(new_h, new_w),  # resized image dimensions (scale to)
    ratio_pad=None,
    padding=False,
    xywh=False,
)

new_boxes#(1)!
>>> array(
    [[  27.454,  277.52,  965.98,   908.2],
    [   58.262,  478.27,  294.42,  1083.3],
    [   803.36,  470.63,  971.66,  1052.4],
    [   265.82,  486.96,  413.98,    1029],
    [        0,  660.64,  75.612,  1048.1],
    [   0.0701,  305.35,  39.073,  389.84]]
)
  1. Cajas delimitadoras escaladas para el nuevo tamaño de la imagen

Conversiones de formato de cuadro delimitador

XYXY → XYWH

Convierte las coordenadas de la caja delimitadora del formato (x1, y1, x2, y2) al formato (x, y, anchura, altura) donde (x1, y1) es la esquina superior izquierda y (x2, y2) es la esquina inferior derecha.

import numpy as np
from ultralytics.utils.ops import xyxy2xywh

xyxy_boxes = np.array(
    [[  22.878,  231.27,  804.98,  756.83,],
    [   48.552,  398.56,  245.35,  902.71,],
    [   669.47,  392.19,  809.72,  877.04,],
    [   221.52,   405.8,  344.98,  857.54,],
    [        0,  550.53,   63.01,  873.44,],
    [   0.0584,  254.46,  32.561,  324.87,]]
)
xywh = xyxy2xywh(xyxy_boxes)

xywh
>>> array(
    [[ 413.93,  494.05,   782.1, 525.56],
    [  146.95,  650.63,   196.8, 504.15],
    [   739.6,  634.62,  140.25, 484.85],
    [  283.25,  631.67,  123.46, 451.74],
    [  31.505,  711.99,   63.01, 322.91],
    [   16.31,  289.67,  32.503,  70.41]]
)

Todas las conversiones del cuadro delimitador

from ultralytics.utils.ops import xywh2xyxy
from ultralytics.utils.ops import xywhn2xyxy # normalized → pixel
from ultralytics.utils.ops import xyxy2xywhn # pixel → normalized
from ultralytics.utils.ops import xywh2ltwh  # xywh → top-left corner, w, h
from ultralytics.utils.ops import xyxy2ltwh  # xyxy → top-left corner, w, h
from ultralytics.utils.ops import ltwh2xywh
from ultralytics.utils.ops import ltwh2xyxy

Consulta el docstring de cada función o visita la página ultralytics.utils.ops página de referencia para leer más sobre cada función.

Trazando

Anotaciones de dibujo

Ultralytics incluye una clase Anotador que puede utilizarse para anotar cualquier tipo de datos. Es más fácil de usar con cuadros delimitadores de detección de objetos, puntos clave de pose y cuadros delimitadores orientados.

Cuadros delimitadores horizontales

import cv2 as cv
import numpy as np
from ultralytics.utils.plotting import Annotator, colors

names { #(1)!
     0: "person",
     5: "bus",
    11: "stop sign",
}

image = cv.imread("ultralytics/assets/bus.jpg")
ann = Annotator(
    image,
    line_width=None,  # default auto-size
    font_size=None,   # default auto-size
    font="Arial.ttf", # must be ImageFont compatible
    pil=False,        # use PIL, otherwise uses OpenCV
)

xyxy_boxes = np.array(
    [[ 5,   22.878,  231.27,  804.98,  756.83,], # class-idx x1 y1 x2 y2
     [ 0,   48.552,  398.56,  245.35,  902.71,],
     [ 0,   669.47,  392.19,  809.72,  877.04,],
     [ 0,   221.52,   405.8,  344.98,  857.54,],
     [ 0,        0,  550.53,   63.01,  873.44,],
     [11,   0.0584,  254.46,  32.561,  324.87,]]
)

for nb, box in enumerate(xyxy_boxes):
    c_idx, *box = box
    label = f"{str(nb).zfill(2)}:{names.get(int(c_idx))}"
    ann.box_label(box, label, color=colors(c_idx, bgr=True))

image_with_bboxes = ann.result()
  1. Se pueden utilizar nombres de model.names cuando trabajar con los resultados de la detección

Cajas delimitadoras orientadas (OBB)

import cv2 as cv
import numpy as np
from ultralytics.utils.plotting import Annotator, colors

obb_names = {10: "small vehicle"}
obb_image = cv.imread("datasets/dota8/images/train/P1142__1024__0___824.jpg")
obb_boxes = np.array(
    [[ 0, 635, 560, 919, 719, 1087, 420, 803,  261,], # class-idx x1 y1 x2 y2 x3 y2 x4 y4
     [ 0, 331,  19, 493, 260, 776,   70, 613, -171,],
     [ 9, 869, 161, 886, 147, 851,  101, 833,  115,]
    ]
)
ann = Annotator(
    obb_image,
    line_width=None,  # default auto-size
    font_size=None,   # default auto-size
    font="Arial.ttf", # must be ImageFont compatible
    pil=False,        # use PIL, otherwise uses OpenCV
)
for obb in obb_boxes:
    c_idx, *obb = obb
    obb = np.array(obb).reshape(-1, 4, 2).squeeze()
    label = f"{names.get(int(c_idx))}"
    ann.box_label(
        obb,
        label,
        color=colors(c_idx, True),
        rotated=True,
    )

image_with_obb = ann.result()

Ver el Annotator Página de referencia para obtener más información.

Varios

Perfiles de código

Comprueba la duración para que el código se ejecute/procese utilizando with o como decorador.

from ultralytics.utils.ops import Profile

with Profile(device=device) as dt:
    pass  # operation to measure

print(dt)
>>> "Elapsed time is 9.5367431640625e-07 s"

Ultralytics Formatos admitidos

¿Quieres o necesitas utilizar los formatos de los tipos de imágenes o vídeos admitidos por Ultralytics mediante programación? Utiliza estas constantes si lo necesitas.

from ultralytics.data.utils import IMG_FORMATS
from ultralytics.data.utils import VID_FORMATS

print(IMG_FORMATS)
>>> ('bmp', 'dng', 'jpeg', 'jpg', 'mpo', 'png', 'tif', 'tiff', 'webp', 'pfm')

Hacer divisible

Calcula el número entero más próximo a x para que sea divisible al dividirlo por y.

from ultralytics.utils.ops import make_divisible

make_divisible(7, 3)
>>> 9
make_divisible(7, 2)
>>> 8


Creado 2024-02-20, Actualizado 2024-05-08
Autores: RizwanMunawar (1), glenn-jocher (3), Burhan-Q (2)

Comentarios