Utilitários Simples

YOLO model code with 3D perspective visualization

O pacote ultralytics fornece uma variedade de utilitários para apoiar, aprimorar e acelerar os teus fluxos de trabalho. Embora existam muitos outros disponíveis, este guia destaca alguns dos mais úteis para desenvolvedores, servindo como uma referência prática para a programação com as ferramentas da Ultralytics.



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

Dados

Autoetiquetagem / Anotações

A anotação de datasets é um processo que consome muitos recursos e tempo. Se tens um modelo Ultralytics YOLO de detecção de objetos treinado em uma quantidade razoável de dados, podes usá-lo com o SAM para anotar automaticamente dados adicionais em formato de segmentação.

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 função não retorna nenhum valor. Para mais detalhes:

Visualizar Anotações de Dataset

Esta função visualiza anotações YOLO em uma imagem antes do treino, ajudando a identificar e corrigir quaisquer anotações erradas que possam levar a resultados de detecção incorretos. Ela desenha caixas delimitadoras, rotula objetos com nomes de classes e ajusta a cor do texto com base na luminância do fundo para melhor legibilidade.

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

Converter Máscaras de Segmentação para o Formato YOLO

Máscaras de Segmentação para o Formato YOLO

Usa isto para converter um dataset de imagens de máscara de segmentação para o formato de segmentação Ultralytics YOLO. Esta função recebe o diretório contendo as imagens de máscara em formato binário e converte-as para o formato de segmentação YOLO.

As máscaras convertidas serão salvas no diretório de saída 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)

Converter COCO para o Formato YOLO

Usa isto para converter anotações JSON COCO para o formato YOLO. Para datasets de detecção de objetos (caixa delimitadora), define use_segments e use_keypoints como False.

from ultralytics.data.converter import convert_coco

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

Para informações adicionais sobre a função convert_coco, visita a página de referência.

Obter Dimensões de Caixas Delimitadoras

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

Converter Caixas Delimitadoras para Segmentos

Com dados existentes de caixas delimitadoras x y w h, converte para segmentos usando a função yolo_bbox2segment. Organiza os arquivos de imagens e anotações da seguinte forma:

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 a página de referência do yolo_bbox2segment para mais informações sobre a função.

Converter Segmentos para Caixas Delimitadoras

Se tens um dataset que usa o formato de dataset de segmentação, podes facilmente convertê-los para caixas delimitadoras verticais (ou horizontais) (formato x y w h) com esta função.

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 como esta função funciona, visita a página de referência.

Utilitários

Compressão de Imagem

Comprime um único arquivo de imagem para um tamanho reduzido, preservando a sua proporção e qualidade. Se a imagem de entrada for menor que a dimensão máxima, ela não será redimensionada.

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)

Divisão Automática de Dataset

Divide automaticamente um dataset em train/val/test e salva as divisões resultantes em arquivos autosplit_*.txt. Esta função usa amostragem aleatória, que é excluída ao usar o argumento fraction para treinamento.

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 a página de referência para detalhes adicionais sobre esta função.

Converter Polígono de Segmento para Máscara Binária

Converte um único polígono (como uma lista) para uma máscara binária do tamanho de imagem especificado. O polígono deve estar na forma de [N, 2], onde N é o número de pontos (x, y) definindo o contorno do polígono.

Aviso

N deve ser sempre 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,
)

Caixas Delimitadoras

Instâncias de Caixa Delimitadora (Horizontal)

Para gerenciar dados de caixas delimitadoras, a classe Bboxes ajuda a converter entre formatos de coordenadas de caixa, escalar dimensões de caixa, calcular áreas, incluir offsets e muito mais.

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 a seção de referência Bboxes para mais atributos e métodos.

Dica

Muitas das funções seguintes (e mais) podem ser acessadas usando a classe Bboxes, mas se preferires trabalhar com as funções diretamente, consulta as subseções seguintes para saber como importá-las de forma independente.

Escalonamento de Caixas

Ao escalar uma imagem para cima ou para baixo, podes escalar adequadamente as coordenadas da caixa delimitadora correspondente para corresponder 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]]
# )

Conversões de Formato de Caixa Delimitadora

XYXY → XYWH

Converte coordenadas de caixa delimitadora do formato (x1, y1, x2, y2) para o formato (x, y, largura, altura), onde (x1, y1) é o canto superior esquerdo e (x2, y2) é o canto inferior direito.

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 as Conversões de Caixa Delimitadora

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.

Plotagem

Utilitários de anotação

A Ultralytics inclui uma classe Annotator para anotar vários tipos de dados. É melhor usada com caixas delimitadoras de detecção de objetos, keypoints de pose e caixas delimitadoras orientadas.

Anotação de Caixa

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

Os nomes podem ser usados a partir de model.names ao trabalhar com resultados de detecção. Consulta também a Página de Referência do Annotator para informações adicionais.

Anotação de Varredura Ultralytics

Anotação de Varredura usando Utilitários 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()

Encontra detalhes adicionais sobre o método sweep_annotator na nossa seção de referência aqui.

Anotação de rótulo adaptável

Aviso

A partir da Ultralytics v8.3.167, circle_label e text_label foram substituídos por uma função unificada adaptive_label. Podes agora especificar o tipo de anotação usando o argumento shape:

  • Retâ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 🚀
Anotação de rótulo adaptável usando Utilitários 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 a Página de Referência do SolutionAnnotator para informações adicionais.

Diversos

Perfilamento de Código

Verifica a duração para o código rodar/processar usando with ou como um 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 Suportados pela Ultralytics

Precisas de usar programaticamente os formatos de imagem ou vídeo suportados na Ultralytics? Usa estas constantes se necessário:

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'}

Tornar Divisível

Calcula o número inteiro mais próximo de x que é uniformemente divisível por y.

from ultralytics.utils.ops import make_divisible

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

FAQ

Que utilitários estão incluídos no pacote Ultralytics para aprimorar os fluxos de trabalho de aprendizado de máquina?

O pacote Ultralytics inclui utilitários projetados para simplificar e otimizar fluxos de trabalho de aprendizado de máquina. Os principais utilitários incluem autoanotação para rotular datasets, conversão de COCO para formato YOLO com convert_coco, compressão de imagens e divisão automática de datasets. Estas ferramentas reduzem o esforço manual, garantem consistência e aprimoram a eficiência do processamento de dados.

Como posso usar a Ultralytics para auto-rotular o meu dataset?

Se tens um modelo de detecção de objetos Ultralytics YOLO pré-treinado, podes usá-lo com o modelo SAM para anotar automaticamente o teu dataset em formato de segmentação. Aqui tens um exemplo:

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 mais detalhes, consulta a seção de referência auto_annotate, ou usa a Plataforma Ultralytics como uma alternativa hospedada e sem código com máscara baseada em cliques via SAM 2.1 ou SAM 3, ou predições de modelos YOLO pré-treinados e ajustados para tarefas de detecção, segmentação e OBB.

Como converto anotações de dataset COCO para o formato YOLO na Ultralytics?

Para converter anotações JSON COCO para o formato YOLO para detecção de objetos, podes usar o utilitário convert_coco. Aqui tens um trecho de código de exemplo:

from ultralytics.data.converter import convert_coco

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

Para informações adicionais, visita a página de referência convert_coco.

Como posso analisar a composição e distribuição do meu dataset?

A Plataforma Ultralytics fornece análises automáticas de dataset: a aba Charts mostra a distribuição das divisões, contagens de classes principais, histogramas de dimensões de imagem e mapas de calor 2D das posições de anotação, ajudando-te a detectar desequilíbrios e valores discrepantes antes do treinamento.

Como posso converter caixas delimitadoras para segmentos na Ultralytics?

Para converter dados existentes de caixas delimitadoras (no formato x y w h) para segmentos, podes usar a função yolo_bbox2segment. Certifica-te de que os teus arquivos estão organizados com diretórios separados para imagens e rótulos.

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 mais informações, visita a página de referência yolo_bbox2segment.

Comentários