Utilidades simples#
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 desarrolladores, sirviendo como una referencia práctica para programar con herramientas de Ultralytics.
Watch: Ultralytics Utilities | Auto Annotation, Explorer API and Dataset Conversion
Datos#
Etiquetado automático / Anotaciones#
La anotación de conjuntos de datos es un proceso que consume muchos recursos y tiempo. Si tienes un modelo de Ultralytics YOLO de detección de objetos 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:
- Consulta la sección de referencia para
annotator.auto_annotatepara obtener más información sobre cómo opera la función. - Úsalo en combinación con la función
segments2boxespara generar también cuadros delimitadores de detección de objetos.
Visualizar 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,
)Convertir máscaras de segmentación al formato YOLO#

Usa esto para convertir un conjunto de datos 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áscaras en formato binario y las convierte al formato de segmentación de 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)Convertir COCO al formato YOLO#
Usa esto para convertir anotaciones JSON de COCO al formato YOLO. Para conjuntos de datos de detección de objetos (cuadros delimitadores), configura tanto use_segments como use_keypoints en 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.
Obtener 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()}")Convertir cuadros delimitadores a segmentos#
Con datos de cuadros delimitadores de 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.txtfrom 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.
Convertir segmentos a cuadros delimitadores#
Si tienes un conjunto de datos que utiliza el formato de conjunto de datos 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, 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) # xywh bounding boxesPara entender cómo funciona esta función, visita la página de referencia.
Utilidades#
Compresió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)División automática de dataset#
Divide automáticamente un conjunto de datos en particiones train/val/test y guarda las particiones 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 obtener detalles adicionales sobre esta función.
Polí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 una matriz 1D plana de coordenadas de N que enumeren valores alternados de x, y que definen el contorno del polígono.
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,
)Cuadros delimitadores (Bounding Boxes)#
Instancias de cuadros delimitadores (horizontales)#
Para gestionar datos de cuadros delimitadores, la clase Bboxes ayuda a convertir entre formatos de coordenadas de cuadros, escalar dimensiones de cuadros, 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 ver más atributos y métodos.
Se puede acceder a muchas de las siguientes funciones (y más) utilizando la clase Bboxes, pero si prefieres trabajar directamente con las funciones, consulta las siguientes subsecciones para saber cómo importarlas de forma independiente.
Escalar cuadros#
Al ampliar o reducir una imagen, 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]]
# )Conversiones de formato de cuadros delimitadores#
XYXY → 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]]
# )Todas 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 docstringsConsulta el docstring de cada función o visita la página de referencia de ultralytics.utils.ops para leer más.
Graficado#
Utilidades 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.
Anotación de cajas#
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()Se pueden 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 (Sweep) 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()Encuentra detalles adicionales sobre el método sweep_annotator en nuestra sección de referencia aquí.
Anotación de etiqueta adaptativa#
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 🚀
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 información adicional.
Miscelánea#
Perfilado de código#
Comprueba la duración de la ejecución/procesamiento del código utilizando 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"Formatos soportados por Ultralytics#
¿Necesitas usar mediante programación los formatos de imagen o video compatibles 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', 'jpg', 'mpo', 'png', 'tif', 'tiff', 'webp'}
print(VID_FORMATS)
# {'asf', 'avi', 'gif', 'm4v', 'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'ts', 'wmv', 'webm'}Hacer divisible#
Calcula el número entero más pequeño mayor o igual que x que sea divisible exactamente por y.
from ultralytics.utils.ops import make_divisible
make_divisible(7, 3)
# >>> 9
make_divisible(7, 2)
# >>> 8FAQ#
¿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 simplificar y optimizar los flujos de trabajo de aprendizaje automático. Las utilidades clave incluyen el autoanotado 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 esfuerzo manual, garantizan la coherencia y mejoran la eficiencia del procesamiento de datos.
¿Cómo puedo usar Ultralytics para autoetiquetar mi dataset?#
Si tienes un modelo de detección de objetos de Ultralytics YOLO previamente entrenado, puedes usarlo con el modelo SAM para autoanotar 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 detalles, consulta la sección de referencia de auto_annotate, o usa la plataforma de Ultralytics como una alternativa alojada y sin código con enmascaramiento basado en clics mediante SAM 2.1 o SAM 3, o predicciones de modelos YOLO previamente entrenados y afinados para tareas de detección, segmentación y OBB.
¿Cómo convierto las anotaciones de un dataset COCO al formato YOLO en Ultralytics?#
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 muestra:
from ultralytics.data.converter import convert_coco
convert_coco(
"coco/annotations/",
use_segments=False,
use_keypoints=False,
cls91to80=True,
)Para obtener información adicional, visita la página de referencia de convert_coco.
¿Cómo puedo analizar la composición y distribución de mi dataset?#
La plataforma de Ultralytics proporciona análisis automáticos de conjuntos de datos: la pestaña Charts muestra la distribución de particiones, el recuento de clases principales, histogramas de dimensiones de imágenes y mapas de calor 2D de las posiciones de las anotaciones, lo que te ayuda a detectar desequilibrios y valores atípicos antes del entrenamiento.
¿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 obtener más información, visita la página de referencia de yolo_bbox2segment.