Ultralytics YOLO27:
Get Started

Utilidades sencillas#

YOLO model code with 3D perspective visualization

El paquete ultralytics ofrece diversas utilidades para respaldar, mejorar y acelerar tus flujos de trabajo. Aunque hay muchas más disponibles, esta guía destaca algunas de las más útiles para desarrolladores y sirve como referencia práctica para programar con las herramientas de Ultralytics.



Ver: Utilidades de Ultralytics | Anotación automática, API de Explorer y conversión de conjuntos de datos

Datos#

Etiquetado automático / Anotaciones#

Anotar un conjunto de datos requiere muchos recursos y tiempo. Si tienes un modelo de detección de objetos Ultralytics YOLO entrenado con una cantidad razonable de datos, puedes usarlo con SAM para anotar automáticamente datos adicionales en formato de segmentación.

from ultralytics.data.annotator import auto_annotate

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

Esta función no devuelve ningún valor. Para obtener más información:

Visualizar las anotaciones del conjunto de datos#

Esta función visualiza las anotaciones YOLO en una imagen antes del entrenamiento, lo que ayuda a identificar y corregir anotaciones erróneas que podrían dar lugar a resultados de detección incorrectos. Dibuja cuadros delimitadores, etiqueta los objetos con los nombres de sus clases y ajusta el color del texto según la luminancia del fondo para mejorar la legibilidad.

from ultralytics.data.utils import visualize_image_annotations

label_map = {  # Define el mapa de etiquetas con todas las etiquetas de clase anotadas.
    0: "person",
    1: "car",
}

# Visualize
visualize_image_annotations(
    "path/to/image.jpg",  # Ruta de la imagen de entrada.
    "path/to/annotations.txt",  # Ruta del archivo de anotaciones de la imagen.
    label_map,
)

Convertir máscaras de segmentación al formato YOLO#

Máscaras de segmentación al formato YOLO

Usa esta función para convertir un conjunto de datos de imágenes con máscaras de segmentación al formato de segmentación de Ultralytics YOLO. Esta función toma el directorio que contiene las imágenes de máscaras en formato binario y las convierte al formato de segmentación YOLO.

Las máscaras convertidas se guardarán en el directorio de salida especificado.

from ultralytics.data.converter import convert_segment_masks_to_yolo_seg

# `classes` es el número total de clases del conjunto de datos.
# El conjunto de datos COCO tiene 80 clases.
convert_segment_masks_to_yolo_seg(masks_dir="path/to/masks_dir", output_dir="path/to/output_dir", classes=80)

Convertir COCO al formato YOLO#

Usa esta función para convertir las anotaciones JSON de COCO al formato YOLO. Para los conjuntos de datos de detección de objetos (cuadros delimitadores), asigna False tanto a use_segments como a use_keypoints.

from ultralytics.data.converter import convert_coco

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

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

Obtener las dimensiones de los cuadros delimitadores#

import cv2

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

model = YOLO("yolo26n.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(f"Bounding Box Width {width.item()}, Height {height.item()}, Area {area.item()}")

Convertir cuadros delimitadores en segmentos#

Con los datos existentes de cuadros delimitadores x y w h, conviértelos en segmentos con la función yolo_bbox2segment. Organiza los archivos de imágenes y anotaciones de la siguiente manera:

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

yolo_bbox2segment(
    im_dir="path/to/images",
    save_dir=None,  # guardado en "labels-segment" junto al directorio de imágenes
    sam_model="sam_b.pt",
)

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

Convertir segmentos en cuadros delimitadores#

Si tienes un conjunto de datos que utiliza el formato de conjunto de datos de segmentación, puedes convertirlo fácilmente en cuadros delimitadores verticales (u horizontales) (formato x y w h) con esta función.

import numpy as np

from ultralytics.utils.ops import segments2boxes

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

segments2boxes([s.reshape(-1, 2) for s in segments])
# >>> array([[804.5, 553. ,  15. , 322. ],
#           [131.5, 354. ,  37. , 112. ],
#           [282.5, 416. ,  35. ,   8. ]],
# dtype=float32) # cuadros delimitadores xywh

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 para reducir su tamaño y conservar su relación de aspecto y calidad. Si la imagen de entrada es menor que la dimensión máxima, no se cambiará su tamaño.

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)

Dividir automáticamente un conjunto de datos#

Divide automáticamente un conjunto de datos en particiones train/val/test y guarda las particiones resultantes en archivos autosplit_*.txt. Esta utilidad crea archivos de partición persistentes; el argumento de entrenamiento fraction selecciona, en cambio, un subconjunto reproducible para una ejecución.

from ultralytics.data.split import autosplit

autosplit(
    path="path/to/images",
    weights=(0.9, 0.1, 0.0),  # (particiones fraccionarias de entrenamiento, validación y prueba)
    annotated_only=False,  # dividir solo las imágenes que tengan un archivo de anotaciones cuando sea True
)

Consulta la página de referencia para obtener más información sobre esta función.

Polígono de segmento a máscara binaria#

Convierte un único polígono (en forma de lista) en una máscara binaria del tamaño de imagen especificado. El polígono debe ser una matriz 1D plana de coordenadas N que enumere valores alternos de x, y para definir el contorno del polígono.

Advertencia

N siempre debe 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])  # (N,) coordenadas x, y en una matriz plana

mask = polygon2mask(
    imgsz,  # tuple
    [polygon],  # entrada como lista
    color=255,  # binario de 8 bits
    downsample_ratio=1,
)

Cuadros delimitadores#

Instancias de cuadros delimitadores (horizontales)#

Para gestionar los datos de cuadros delimitadores, la clase Bboxes ayuda a convertir entre formatos de coordenadas de cuadros, escalar sus dimensiones, 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]]
# )

Consulta la sección de referencia de Bboxes para conocer más atributos y métodos.

Consejo

Puedes acceder a muchas de las siguientes funciones (y a otras más) mediante la clase Bboxes, pero si prefieres trabajar directamente con las funciones, consulta las subsecciones siguientes para saber cómo importarlas por separado.

Escalar cuadros#

Al ampliar o reducir una imagen, puedes escalar adecuadamente las coordenadas de los cuadros delimitadores correspondientes para que coincidan mediante 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),  # dimensiones de la imagen original
    boxes=xyxy_boxes,  # cuadros de la imagen original
    img0_shape=(new_h, new_w),  # dimensiones de la imagen redimensionada (escalar a)
    ratio_pad=None,
    padding=False,
    xywh=False,
)

print(new_boxes)
# >>> 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]]
# )

Conversiones de formato de cuadros delimitadores#

XYXY → XYWH#

Convierte las coordenadas de los cuadros delimitadores del formato (x1, y1, x2, y2) al formato (x, y, ancho, alto), 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 de cuadros delimitadores#

from ultralytics.utils.ops import (
    ltwh2xywh,
    ltwh2xyxy,
    xywh2ltwh,  # xywh → esquina superior izquierda, w, h
    xywh2xyxy,
    xywhn2xyxy,  # normalizado → píxel
    xyxy2ltwh,  # xyxy → esquina superior izquierda, w, h
    xyxy2xywhn,  # píxel → normalizado
)

for func in (ltwh2xywh, ltwh2xyxy, xywh2ltwh, xywh2xyxy, xywhn2xyxy, xyxy2ltwh, xyxy2xywhn):
    print(help(func))  # imprimir las cadenas de documentación de las funciones

Consulta la cadena de documentación de cada función o visita la página de referencia de ultralytics.utils.ops para obtener más información.

Gráficos#

Utilidades de anotación#

Ultralytics incluye una clase Annotator para anotar distintos tipos de datos. Es especialmente útil con cuadros delimitadores de detección de objetos, puntos clave de pose y cuadros delimitadores orientados.

Anotación de cuadros#

Ejemplos de Python con Ultralytics YOLO 🚀
import cv2 as cv
import numpy as np

from ultralytics.utils.plotting import Annotator, colors

names = {
    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()

Puedes usar nombres de model.names al trabajar con resultados de detección. Consulta también la página de referencia de Annotator para obtener más información.

Anotación de barrido de Ultralytics#

Anotación de barrido con las utilidades de Ultralytics
import sys

import cv2
import numpy as np

from ultralytics import YOLO
from ultralytics.solutions.solutions import SolutionAnnotator
from ultralytics.utils.plotting import colors

# User defined video path and model file
cap = cv2.VideoCapture("path/to/video.mp4")
model = YOLO(model="yolo26s-seg.pt")  # Model file, e.g., yolo26s.pt or yolo26m-seg.pt

if not cap.isOpened():
    print("Error: Could not open video.")
    sys.exit()

# Initialize the video writer object.
w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))
video_writer = cv2.VideoWriter("ultralytics.avi", cv2.VideoWriter_fourcc(*"mp4v"), fps, (w, h))

masks = None  # Initialize variable to store masks data
f = 0  # Initialize frame count variable for enabling mouse event.
line_x = w  # Store width of line.
dragging = False  # Initialize bool variable for line dragging.
classes = model.names  # Store model classes names for plotting.
window_name = "Ultralytics Sweep Annotator"

def drag_line(event, x, _, flags, param):
    """Mouse callback function to enable dragging a vertical sweep line across the video frame."""
    global line_x, dragging
    if event == cv2.EVENT_LBUTTONDOWN or (flags & cv2.EVENT_FLAG_LBUTTON):
        line_x = max(0, min(x, w))
        dragging = True

while cap.isOpened():  # Loop over the video capture object.
    ret, im0 = cap.read()
    if not ret:
        break
    f = f + 1  # Increment frame count.
    count = 0  # Re-initialize count variable on every frame for precise counts.
    results = model.track(im0, persist=True)[0]

    if f == 1:
        cv2.namedWindow(window_name)
        cv2.setMouseCallback(window_name, drag_line)

    annotator = SolutionAnnotator(im0)

    if results.boxes.is_track:
        if results.masks is not None:
            masks = [np.array(m, dtype=np.int32) for m in results.masks.xy]

        boxes = results.boxes.xyxy.tolist()
        track_ids = results.boxes.id.int().cpu().tolist()
        clss = results.boxes.cls.cpu().tolist()

        for mask, box, cls, t_id in zip(masks or [None] * len(boxes), boxes, clss, track_ids):
            color = colors(t_id, True)  # Assign different color to each tracked object.
            label = f"{classes[cls]}:{t_id}"
            if mask is not None and mask.size > 0:
                if box[0] > line_x:
                    count += 1
                    cv2.polylines(im0, [mask], True, color, 2)
                    x, y = mask.min(axis=0)
                    (w_m, _), _ = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
                    cv2.rectangle(im0, (x, y - 20), (x + w_m, y), color, -1)
                    cv2.putText(im0, label, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
            else:
                if box[0] > line_x:
                    count += 1
                    annotator.box_label(box=box, color=color, label=label)

    # Generate draggable sweep line
    annotator.sweep_annotator(line_x=line_x, line_y=h, label=f"COUNT:{count}")

    cv2.imshow(window_name, im0)
    video_writer.write(im0)
    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

# Release the resources
cap.release()
video_writer.release()
cv2.destroyAllWindows()

Encontrarás más información sobre el método sweep_annotator en nuestra sección de referencia aquí.

Anotación de etiquetas adaptativas#

SolutionAnnotator.adaptive_label dibuja una etiqueta cuya forma se elige con el argumento shape (que sustituye a los métodos anteriores circle_label y text_label):

  • Rectángulo: annotator.adaptive_label(box, label=names[int(cls)], color=colors(cls, True), shape="rect")
  • Círculo: annotator.adaptive_label(box, label=names[int(cls)], color=colors(cls, True), shape="circle")


Ver: Guía detallada de anotaciones de texto y círculos con demostraciones en directo en Python | Anotaciones de Ultralytics 🚀
Anotación de etiquetas adaptativas con las utilidades de Ultralytics
import cv2

from ultralytics import YOLO
from ultralytics.solutions.solutions import SolutionAnnotator
from ultralytics.utils.plotting import colors

model = YOLO("yolo26s.pt")
names = model.names
cap = cv2.VideoCapture("path/to/video.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 = SolutionAnnotator(im0)
    results = model.predict(im0)[0]
    boxes = results.boxes.xyxy.cpu()
    clss = results.boxes.cls.cpu().tolist()

    for box, cls in zip(boxes, clss):
        annotator.adaptive_label(box, label=names[int(cls)], color=colors(cls, True), shape="circle")
    writer.write(im0)
    cv2.imshow("Ultralytics circle annotation", im0)

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

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

Consulta la página de referencia de SolutionAnnotator para obtener más información.

Varios#

Perfilado del código#

Comprueba cuánto tarda el código en ejecutarse o procesarse con with o como decorador.

from ultralytics.utils.ops import Profile

with Profile(device="cuda:0") as dt:
    pass  # operación que se va a medir

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

Formatos compatibles con Ultralytics#

¿Necesitas usar mediante programación los formatos de imagen o vídeo compatibles con Ultralytics? Usa estas constantes si las necesitas:

from ultralytics.data.utils import IMG_FORMATS, VID_FORMATS

print(IMG_FORMATS)
# {'avif', 'bmp', 'dng', 'heic', 'heif', 'jp2', 'jpeg', 'jpg', 'mpo', 'png', 'tif', 'tiff', 'webp'}

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

Redondear al múltiplo#

Calcula el número entero más pequeño mayor o igual que x que sea divisible entre y.

from ultralytics.utils.ops import make_divisible

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

Preguntas frecuentes#

  • El paquete Ultralytics incluye utilidades diseñadas para simplificar y optimizar los flujos de trabajo de aprendizaje automático. Entre las utilidades principales se encuentran la anotación automática para etiquetar conjuntos de datos, la conversión de COCO al formato YOLO con convert_coco, la compresión de imágenes y la división automática de conjuntos de datos. Estas herramientas reducen el trabajo manual, garantizan la coherencia y mejoran la eficiencia del procesamiento de datos.

  • Si tienes un modelo de detección de objetos Ultralytics YOLO preentrenado, puedes usarlo con el modelo SAM para anotar automáticamente tu conjunto de datos en formato de segmentación. Aquí tienes un ejemplo:

    from ultralytics.data.annotator import auto_annotate
    
    auto_annotate(
        data="path/to/new/data",
        det_model="yolo26n.pt",
        sam_model="mobile_sam.pt",
        device="cuda",
        output_dir="path/to/save_labels",
    )

    Para obtener más información, consulta la sección de referencia de auto_annotate o utiliza Ultralytics Platform como alternativa alojada que no requiere código, con máscaras que se crean haciendo clic mediante SAM 2.1, SAM 3 o SAM 3.1, o predicciones de modelos YOLO preentrenados y ajustados para tareas de detección, segmentación y OBB.

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

    from ultralytics.data.converter import convert_coco
    
    convert_coco(
        "coco/annotations/",
        use_segments=False,
        use_keypoints=False,
        cls91to80=True,
    )

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

  • Ultralytics Platform proporciona análisis automáticos de conjuntos de datos: la pestaña Charts muestra la distribución de las particiones, el recuento de las clases más frecuentes, histogramas de las dimensiones de las imágenes y mapas de calor 2D de la posición de las anotaciones, lo que te ayuda a detectar desequilibrios y valores atípicos antes del entrenamiento.

  • Para convertir datos existentes de cajas delimitadoras (en formato x y w h) en segmentos, puedes usar la función yolo_bbox2segment. Asegúrate de que tus archivos estén organizados en 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,  # guardado en "labels-segment" junto al directorio de imágenes
        sam_model="sam_b.pt",
    )

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

Comentarios