Utilidades sencillas
En ultralytics
viene con una miríada de utilidades que pueden apoyar, mejorar y acelerar sus 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 buen punto de referencia para aprender a programar.
Observa: Ultralytics Utilidades | Anotación automática, API Explorer y conversión de conjuntos de datos
Datos
Autoetiquetado / Anotaciones
La anotación de conjuntos de datos es un proceso que consume muchos recursos y tiempo. Si dispone de un modelo dedetección de objetos YOLO entrenado en una cantidad razonable de datos, puede utilizarlo y SAM para auto-anotar datos adicionales (formato de segmentación).
from ultralytics.data.annotator import auto_annotate
auto_annotate( # (1)!
data="path/to/new/data",
det_model="yolo11n.pt",
sam_model="mobile_sam.pt",
device="cuda",
output_dir="path/to/save_labels",
)
-
Esta función no devuelve nada
-
Consulte la sección de referencias para
annotator.auto_annotate
para saber más sobre el funcionamiento de esta función. -
Utilizar en combinación con el función
segments2boxes
para generar también cuadros delimitadores de detección de objetos
Convertir máscaras de segmentación en formato YOLO
Se utiliza para convertir un conjunto de datos de imágenes de máscaras de segmentación al formato YOLO
formato de segmentación.
Esta función toma el directorio que contiene las imágenes de máscara en formato binario y las convierte en 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)
Convertir COCO en 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,
)
- Esta función no devuelve nada
Para más información sobre el convert_coco
función, visite la página de referencia
Obtener las dimensiones del cuadro delimitador
from ultralytics.utils.plotting import Annotator
from ultralytics import YOLO
import cv2
model = YOLO('yolo11n.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 los x y w h
convertir a segmentos mediante 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",
)
- Esta función no devuelve nada
Visite el yolo_bbox2segment
página de referencia para más información sobre la función.
Convertir segmentos en cuadros delimitadores
Si tiene un conjunto de datos que utiliza la función formato del conjunto de datos de segmentación puede convertirlos fácilmente en cuadros delimitadores verticales (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, visite la página de referencia
Servicios
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)!
- 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 guardar las divisiones resultantes en autosplit_*.txt
archivos. Esta función utilizará el muestreo aleatorio, que no se incluye cuando se utiliza fraction
argumento a favor de 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
)
- Esta función no devuelve nada
Consulte la página Referencia para obtener más información 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
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]) # (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, el Bboxes
le ayudará a convertir entre formatos de coordenadas de cajas, escalar dimensiones de 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]]
# )
Véase 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) mediante la función Bboxes
clase pero si prefiere trabajar con las funciones directamente, consulte 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]]
# )
- Cuadros delimitadores escalados 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 de Bounding Box
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
Consulte la documentación de cada función o visite la página ultralytics.utils.ops
página de referencia para leer más sobre cada función.
Trazado
Anotaciones de dibujo
Ultralytics incluye una clase Annotator 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.
Ultralytics Anotación de barrido
Python Ejemplos con YOLO11 🚀
import cv2
from ultralytics import YOLO
from ultralytics.utils.plotting import Annotator, colors
# User defined video path and model file
cap = cv2.VideoCapture("Path/to/video/file.mp4")
model = YOLO(model="yolo11s-seg.pt") # Model file i.e. yolo11s.pt or yolo11m-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, y, flags, param): # Mouse callback for dragging line.
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.
annotator = Annotator(im0)
results = model.track(im0, persist=True) # Track objects using track method.
if f == 1:
cv2.namedWindow(window_name)
cv2.setMouseCallback(window_name, drag_line)
if results[0].boxes.id is not None:
if results[0].masks is not None:
masks = results[0].masks.xy
track_ids = results[0].boxes.id.int().cpu().tolist()
clss = results[0].boxes.cls.cpu().tolist()
boxes = results[0].boxes.xyxy.cpu()
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.
if mask is not None and mask.size > 0:
# If you want to overlay the masks
# mask[:, 0] = np.clip(mask[:, 0], line_x, w)
# mask_img = cv2.fillPoly(im0.copy(), [mask.astype(int)], color)
# cv2.addWeighted(mask_img, 0.5, im0, 0.5, 0, im0)
if box[0] > line_x:
count += 1
annotator.seg_bbox(mask=mask, mask_color=color, label=str(classes[cls]))
else:
if box[0] > line_x:
count += 1
annotator.box_label(box=box, color=color, label=str(classes[cls]))
annotator.sweep_annotator(line_x=line_x, line_y=h, label=f"COUNT:{count}") # Display the sweep
cv2.imshow(window_name, im0)
video_writer.write(im0)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cap.release() # Release the video capture.
video_writer.release() # Release the video writer.
cv2.destroyAllWindows() # Destroy all opened windows.
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()
- 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 circular Etiqueta circular
Observa: Guía en profundidad de anotaciones de texto y círculos con Python Demostraciones en directo | Ultralytics Anotaciones 🚀
import cv2
from ultralytics import YOLO
from ultralytics.utils.plotting import Annotator
model = YOLO("yolo11s.pt")
names = model.names
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)
results = model.predict(im0)
boxes = results[0].boxes.xyxy.cpu()
clss = results[0].boxes.cls.cpu().tolist()
for box, cls in zip(boxes, clss):
annotator.circle_label(box, label=names[int(cls)])
writer.write(im0)
cv2.imshow("Ultralytics circle annotation", im0)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
writer.release()
cap.release()
cv2.destroyAllWindows()
Cuadros delimitadores Texto Anotación Texto Etiqueta
import cv2
from ultralytics import YOLO
from ultralytics.utils.plotting import Annotator
model = YOLO("yolo11s.pt")
names = model.names
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)
results = model.predict(im0)
boxes = results[0].boxes.xyxy.cpu()
clss = results[0].boxes.cls.cpu().tolist()
for box, cls in zip(boxes, clss):
annotator.text_label(box, label=names[int(cls)])
writer.write(im0)
cv2.imshow("Ultralytics text annotation", im0)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
writer.release()
cap.release()
cv2.destroyAllWindows()
Véase el Annotator
Página de referencia para más información.
Varios
Perfiles de código
Compruebe la duración de la ejecución/procesamiento del código mediante 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
¿Desea o necesita 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 de aprendizaje automático?
El paquete Ultralytics incluye una serie de utilidades diseñadas para agilizar y optimizar los flujos de trabajo de aprendizaje automático. Entre las principales utilidades se incluyen la anotación automática para etiquetar conjuntos de datos, la conversión de formato COCO a YOLO con convert_coco, la compresión de imágenes y la división automática de conjuntos de datos. El objetivo de estas herramientas es reducir el esfuerzo manual, garantizar la coherencia y mejorar la eficiencia del procesamiento de datos.
¿Cómo puedo utilizar Ultralytics para autoetiquetar mi conjunto de datos?
Si dispone de un modelo de detección de objetos preentrenado en Ultralytics YOLO , puede utilizarlo con el modelo SAM para auto-anotar su 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="yolo11n.pt",
sam_model="mobile_sam.pt",
device="cuda",
output_dir="path/to/save_labels",
)
Para más detalles, consulte la sección de referencia de auto_annotate.
¿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, puede utilizar la función convert_coco
utilidad. He aquí 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, visite 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 el 8.1.0
para mejorar la comprensión del conjunto de datos. Permite utilizar consultas de texto para encontrar instancias de objetos en el conjunto de datos, lo que facilita el análisis y la gestión de los datos. Esta herramienta proporciona información valiosa sobre la composición y distribución del conjunto de datos, lo que ayuda 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
) a segmentos, puede utilizar el yolo_bbox2segment
función. Asegúrese de que sus 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, visite la página de referenciayolo_bbox2segment.