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.

import numpy as np
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!

import numpy as np
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")
print(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,
)

print(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)

print(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 (
    ltwh2xywh,
    ltwh2xyxy,
    xywh2ltwh,  # xywh 鈫 top-left corner, w, h
    xywh2xyxy,
    xywhn2xyxy,  # normalized 鈫 pixel
    xyxy2ltwh,  # xyxy 鈫 top-left corner, w, h
    xyxy2xywhn,  # pixel 鈫 normalized
)

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"{obb_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="cuda:0") 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, 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-19
Autores: glenn-jocher (5), RizwanMunawar (1), Burhan-Q (2)

Comentarios