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
)

for func in (ltwh2xywh, ltwh2xyxy, xywh2ltwh, xywh2xyxy, xywhn2xyxy, xyxy2ltwh, xyxy2xywhn):
    print(help(func))  # print function docstrings

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

Cuadros delimitadores Anotación de círculo (etiqueta de círculo)

import cv2

from ultralytics import YOLO
from ultralytics.utils.plotting import Annotator, colors

model = YOLO("yolov8s.pt")
cap = cv2.VideoCapture("path/to/video/file.mp4")

w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))
writer = cv2.VideoWriter("Ultralytics circle annotation.avi", cv2.VideoWriter_fourcc(*"MJPG"), fps, (w, h))

while True:
    ret, im0 = cap.read()
    if not ret:
        break

    annotator = Annotator(im0, line_width=2)

    results = model.predict(im0)
    boxes = results[0].boxes.xyxy.cpu()
    clss = results[0].boxes.cls.cpu().tolist()

    for box, cls in zip(boxes, clss):
        x1, y1 = int((box[0] + box[2]) // 2), int((box[1] + box[3]) // 2)
        annotator.circle_label(box, label=model.names[int(cls)], color=colors(int(cls), True))

    writer.write(im0)
    cv2.imshow("Ultralytics circle annotation", im0)

    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

writer.release()
cap.release()
cv2.destroyAllWindows()

Anotación de texto de cuadros delimitadores (etiqueta de texto)

import cv2

from ultralytics import YOLO
from ultralytics.utils.plotting import Annotator, colors

model = YOLO("yolov8s.pt")
cap = cv2.VideoCapture("path/to/video/file.mp4")

w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))
writer = cv2.VideoWriter("Ultralytics text annotation.avi", cv2.VideoWriter_fourcc(*"MJPG"), fps, (w, h))

while True:
    ret, im0 = cap.read()
    if not ret:
        break

    annotator = Annotator(im0, line_width=2)

    results = model.predict(im0)
    boxes = results[0].boxes.xyxy.cpu()
    clss = results[0].boxes.cls.cpu().tolist()

    for box, cls in zip(boxes, clss):
        x1, y1 = int((box[0] + box[2]) // 2), int((box[1] + box[3]) // 2)
        annotator.text_label(box, label=model.names[int(cls)], color=colors(int(cls), True))

    writer.write(im0)
    cv2.imshow("Ultralytics text annotation", im0)

    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

writer.release()
cap.release()
cv2.destroyAllWindows()

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)
# {'tiff', 'pfm', 'bmp', 'mpo', 'dng', 'jpeg', 'png', 'webp', 'tif', 'jpg'}

print(VID_FORMATS)
# {'avi', 'mpg', 'wmv', 'mpeg', 'm4v', 'mov', 'mp4', 'asf', 'mkv', 'ts', 'gif', 'webm'}

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

PREGUNTAS FRECUENTES

¿Qué utilidades se incluyen en el paquete Ultralytics para mejorar los flujos de trabajo del aprendizaje automático?

El paquete Ultralytics incluye diversas utilidades diseñadas para agilizar y optimizar los flujos de trabajo del aprendizaje automático. Entre las principales utilidades se incluyen la anotación automática para etiquetar conjuntos de datos, la conversión del formato COCO a YOLO con convert_coco, la compresión de imágenes y la división automática de conjuntos de datos. Estas herramientas pretenden reducir el esfuerzo manual, garantizar la coherencia y mejorar la eficacia del procesamiento de datos.

¿Cómo puedo utilizar Ultralytics para autoetiquetar mi conjunto de datos?

Si tienes un modelo de detección de objetos preentrenado en Ultralytics YOLO , puedes utilizarlo con el SAM para auto-anotar tu conjunto de datos en formato de segmentación. He aquí un ejemplo:

from ultralytics.data.annotator import auto_annotate

auto_annotate(
    data="path/to/new/data",
    det_model="yolov8n.pt",
    sam_model="mobile_sam.pt",
    device="cuda",
    output_dir="path/to/save_labels",
)

Para más detalles, consulta la sección de referencia auto_anotar.

¿Cómo convierto las anotaciones del conjunto de datos COCO al formato YOLO en Ultralytics?

Para convertir las anotaciones JSON de COCO al formato YOLO para la detección de objetos, puedes utilizar la función convert_coco utilidad. Aquí tienes un fragmento de código de ejemplo:

from ultralytics.data.converter import convert_coco

convert_coco(
    "../datasets/coco/annotations/",
    use_segments=False,
    use_keypoints=False,
    cls91to80=True,
)

Para más información, visita la página de referencia de convert_coco.

¿Para qué sirve el explorador de datos YOLO del paquete Ultralytics ?

En YOLO Explorador es una potente herramienta introducida en la 8.1.0 actualización para mejorar la comprensión del conjunto de datos. Te permite utilizar consultas de texto para encontrar instancias de objetos en tu conjunto de datos, lo que facilita el análisis y la gestión de tus datos. Esta herramienta proporciona información valiosa sobre la composición y distribución del conjunto de datos, ayudando a mejorar la formación y el rendimiento del modelo.

¿Cómo puedo convertir cuadros delimitadores en segmentos en Ultralytics?

Para convertir los datos de los recuadros delimitadores existentes (en x y w h formato) a segmentos, puedes utilizar yolo_bbox2segment función. Asegúrate de que tus archivos están organizados con directorios separados para las imágenes y las etiquetas.

from ultralytics.data.converter import yolo_bbox2segment

yolo_bbox2segment(
    im_dir="path/to/images",
    save_dir=None,  # saved to "labels-segment" in the images directory
    sam_model="sam_b.pt",
)

Para más información, visita la página de referenciayolo_bbox2segment.



Creado 2024-02-20, Actualizado 2024-07-04
Autores: glenn-jocher (9), ambitious-octopus (1), IvorZhu331 (1), RizwanMunawar (1), Burhan-Q (2)

Comentarios