Meet YOLO26: next-gen vision AI.

Link to this sectionUtilidades simples#

YOLO model code with 3D perspective visualization

El paquete ultralytics ofrece una variedad de 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 los desarrolladores, sirviendo como una referencia práctica para programar con herramientas de Ultralytics.



Watch: Ultralytics Utilities | Auto Annotation, Explorer API and Dataset Conversion

Link to this sectionDatos#

Link to this sectionEtiquetado automático / Anotaciones#

La anotación de datasets es un proceso que consume mucho tiempo y recursos. Si tienes un modelo de detección de objetos de Ultralytics YOLO entrenado con una cantidad razonable de datos, puedes usarlo con SAM para autoanotar 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 más detalles:

Link to this sectionVisualizar anotaciones del dataset#

Esta función visualiza las anotaciones YOLO en una imagen antes del entrenamiento, lo que ayuda a identificar y corregir cualquier anotación incorrecta que pueda conducir a resultados de detección erróneos. Dibuja cuadros delimitadores, etiqueta objetos con nombres de clase y ajusta el color del texto según la luminancia del fondo para una mejor legibilidad.

from ultralytics.data.utils import visualize_image_annotations

label_map = {  # Define the label map with all annotated class labels.
    0: "person",
    1: "car",
}

# Visualize
visualize_image_annotations(
    "path/to/image.jpg",  # Input image path.
    "path/to/annotations.txt",  # Annotation file path for the image.
    label_map,
)

Link to this sectionConvertir máscaras de segmentación al formato YOLO#

Máscaras de segmentación a formato YOLO

Utiliza esto para convertir un dataset de imágenes de 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áscara 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

# The classes here is the total classes in the dataset.
# for COCO dataset we have 80 classes.
convert_segment_masks_to_yolo_seg(masks_dir="path/to/masks_dir", output_dir="path/to/output_dir", classes=80)

Link to this sectionConvertir COCO al formato YOLO#

Utiliza esto para convertir anotaciones JSON de COCO al formato YOLO. Para datasets de detección de objetos (cuadros delimitadores), establece use_segments y use_keypoints como False.

from ultralytics.data.converter import convert_coco

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

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

Link to this sectionObtener dimensiones de 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()}")

Link to this sectionConvertir cuadros delimitadores a segmentos#

Con datos de cuadros delimitadores x y w h existentes, conviértelos a segmentos usando 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,  # saved to "labels-segment" in images directory
    sam_model="sam_b.pt",
)

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

Link to this sectionConvertir segmentos a cuadros delimitadores#

Si tienes un dataset que utiliza el formato de dataset de segmentación, puedes convertirlos 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, ..., 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.

Link to this sectionUtilidades#

Link to this sectionCompresión de imágenes#

Comprime un solo archivo de imagen a un tamaño reducido mientras conservas su relación de aspecto y calidad. Si la imagen de entrada es más pequeña 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)

Link to this sectionDivisión automática de dataset#

Divide automáticamente un dataset en divisiones de train/val/test y guarda las divisiones resultantes en archivos autosplit_*.txt. Esta función utiliza muestreo aleatorio, el cual se excluye al usar el argumento fraction para el entrenamiento.

from ultralytics.data.split import autosplit

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

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

Link to this sectionPolígono de segmento a máscara binaria#

Convierte un solo polígono (como una lista) en una máscara binaria del tamaño de imagen especificado. El polígono debe ser un array 1D plano de N coordenadas que enumere valores x, y alternos que definan el contorno del polígono.

Advertencia

N debe ser siempre 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,
)

Link to this sectionCuadros delimitadores (Bounding Boxes)#

Link to this sectionInstancias de cuadros delimitadores (horizontales)#

Para gestionar datos de cuadros delimitadores, la clase Bboxes ayuda a convertir entre formatos de coordenadas de caja, escalar dimensiones de caja, calcular áreas, incluir desplazamientos y 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 más atributos y métodos.

Consejo

Muchas de las siguientes funciones (y más) se pueden acceder utilizando la clase Bboxes, pero si prefieres trabajar con las funciones directamente, consulta las siguientes subsecciones para saber cómo importarlas de forma independiente.

Link to this sectionEscalar cuadros#

Al escalar una imagen hacia arriba o hacia abajo, puedes escalar adecuadamente las coordenadas de los cuadros delimitadores correspondientes para que coincidan usando 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)
# >>> 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]]
# )

Link to this sectionConversiones de formato de cuadros delimitadores#

Link to this sectionXYXY → XYWH#

Convierte las coordenadas del cuadro delimitador 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]]
# )

Link to this sectionTodas las conversiones de cuadros delimitadores#

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

See the docstring for each function or visit the ultralytics.utils.ops reference page to read more.

Link to this sectionGraficado#

Link to this sectionUtilidades de anotación#

Ultralytics incluye una clase Annotator para anotar varios tipos de datos. Se utiliza mejor con cuadros delimitadores de detección de objetos, puntos clave de pose y cuadros delimitadores orientados.

Link to this sectionAnotación de cajas#

Ejemplos de Python usando 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()

Los nombres se pueden usar desde model.names al trabajar con resultados de detección. También consulta la página de referencia de Annotator para obtener información adicional.

Link to this sectionAnotación de barrido (Sweep) de Ultralytics#

Anotación de barrido usando utilidades de Ultralytics
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.")
    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()

Encuentra detalles adicionales sobre el método sweep_annotator en nuestra sección de referencia aquí.

Link to this sectionAnotación de etiqueta adaptativa#

Advertencia

A partir de Ultralytics v8.3.167, circle_label y text_label han sido reemplazados por una función unificada adaptive_label. Ahora puedes especificar el tipo de anotación usando el argumento shape:

  • 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")


Watch: In-Depth Guide to Text & Circle Annotations with Python Live Demos | Ultralytics Annotations 🚀
Anotación de etiqueta adaptativa usando 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 más información.

Link to this sectionMiscelánea#

Link to this sectionPerfilado de código#

Comprueba la duración de ejecución/procesamiento del código, ya sea usando with o como un 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"

Link to this sectionFormatos soportados por Ultralytics#

¿Necesitas utilizar programáticamente los formatos de imagen o vídeo soportados en Ultralytics? Usa estas constantes si es necesario:

from ultralytics.data.utils import IMG_FORMATS, VID_FORMATS

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

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

Link to this sectionHacer divisible#

Calcula el número entero más pequeño mayor o igual a x que es divisible uniformemente por y.

from ultralytics.utils.ops import make_divisible

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

Link to this sectionFAQ#

Link to this section¿Qué utilidades están incluidas en el paquete Ultralytics para mejorar los flujos de trabajo de aprendizaje automático?#

El paquete Ultralytics incluye utilidades diseñadas para agilizar y optimizar los flujos de trabajo de aprendizaje automático. Las utilidades clave incluyen la autoanotación para etiquetar datasets, la conversión de COCO al formato YOLO con convert_coco, la compresión de imágenes y la división automática de datasets. Estas herramientas reducen el esfuerzo manual, garantizan la consistencia y mejoran la eficiencia del procesamiento de datos.

Link to this section¿Cómo puedo usar Ultralytics para autoetiquetar mi dataset?#

Si tienes un modelo de detección de objetos Ultralytics YOLO preentrenado, puedes usarlo con el modelo SAM para autoanotar tu dataset 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 más detalles, consulta la sección de referencia de auto_annotate, o usa la plataforma Ultralytics como una alternativa alojada sin código con enmascaramiento basado en clics a través de SAM 2.1 o SAM 3, o predicciones de modelos YOLO preentrenados y ajustados para tareas de detección, segmentación y OBB.

Link to this section¿Cómo convierto las anotaciones de un dataset COCO al formato YOLO en Ultralytics?#

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

from ultralytics.data.converter import convert_coco

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

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

Link to this section¿Cómo puedo analizar la composición y distribución de mi dataset?#

La plataforma Ultralytics proporciona análisis automáticos del dataset: la pestaña Charts muestra la distribución de las divisiones, los recuentos de las clases principales, histogramas de dimensiones de imagen y mapas de calor 2D de las posiciones de las anotaciones, lo que te ayuda a detectar desequilibrios y valores atípicos antes de entrenar.

Link to this section¿Cómo puedo convertir cuadros delimitadores a segmentos en Ultralytics?#

Para convertir datos de cuadros delimitadores existentes (en formato x y w h) a segmentos, puedes usar la función yolo_bbox2segment. Asegúrate de que tus archivos estén organizados con directorios separados para imágenes y 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 referencia de yolo_bbox2segment.

Comentarios