Saltar para o conteúdo

Utilitários simples

código com perspetiva

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



Ver: Ultralytics Utilitários | Anotação automática, API do explorador e conversão de conjuntos de dados

Dados

Etiquetagem automática / Anotações

A anotação de conjuntos de dados é um processo que consome muitos recursos e tempo. Se tiver um modelo dedeteção de objectos Ultralytics YOLO treinado com uma quantidade razoável de dados, pode utilizá-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="yolo11n.pt",
    sam_model="mobile_sam.pt",
    device="cuda",
    output_dir="path/to/save_labels",
)

Esta função não devolve qualquer valor. Para mais pormenores:

Visualizar anotações de conjuntos de dados

Esta função visualiza YOLO anotações numa imagem antes do treino, ajudando a identificar e corrigir quaisquer anotações erradas que possam levar a resultados de deteção incorrectos. Desenha caixas delimitadoras, rotula objectos com nomes de classes e ajusta a cor do texto com base na luminância do fundo para uma 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

Utilize esta opção para converter um conjunto de dados de imagens de máscara de segmentação para o Ultralytics YOLO do Ultralytics. Esta função utiliza o diretório que contém as imagens de máscara de formato binário e converte-as para o formato de segmentação YOLO .

As máscaras convertidas serão guardadas 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

Utilize isto para converter COCO anotações JSON no formato YOLO . Para conjuntos de dados de deteção de objectos (caixa delimitadora), defina ambos use_segments e use_keypoints para False.

from ultralytics.data.converter import convert_coco

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

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

Obter dimensões da caixa delimitadora

import cv2

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

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

Converter caixas delimitadoras em segmentos

Com os actuais x y w h dados da caixa delimitadora, converter em segmentos utilizando o yolo_bbox2segment função. Organize os ficheiros para 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",
)

Visite o yolo_bbox2segment página de referência para mais informações sobre a função.

Converter segmentos em caixas delimitadoras

Se tiver um conjunto de dados que utilize o formato do conjunto de dados de segmentação, pode facilmente convertê-las em caixas delimitadoras verticais (ou horizontais) (x y w h formato) 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 compreender o funcionamento desta função, visite a página de referência.

Utilidades

Compressão de imagem

Comprime um único ficheiro de imagem para um tamanho reduzido, preservando a sua relação de aspeto e qualidade. Se a imagem de entrada for mais pequena do que a dimensão máxima, 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)

Conjunto de dados de divisão automática

Dividir automaticamente um conjunto de dados em train/val/test e guardar as divisões resultantes em autosplit_*.txt ficheiros. Esta função utiliza a amostragem aleatória, que é excluída quando se utiliza a função fraction argumento para a formação.

from ultralytics.data.utils 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
)

Consulte a página Referência para obter mais informações sobre esta função.

Segmento-polígono para máscara binária

Converte um único polígono (como uma lista) numa máscara binária com o tamanho de imagem especificado. O polígono deve ter a forma de [N, 2], em que N é o número de (x, y) pontos que definem o contorno do polígono.

Aviso

N deve sempre ser uniforme.

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 de delimitação

Instâncias de caixa delimitadora (horizontal)

Para gerir os dados da caixa delimitadora, o Bboxes A classe ajuda a converter entre formatos de coordenadas de caixa, dimensionar dimensões de caixa, calcular áreas, incluir deslocamentos 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]]
# )

Ver o Bboxes secção de referência para mais atributos e métodos.

Dica

Muitas das seguintes funções (e outras) podem ser acedidas utilizando a função Bboxes classemas se preferir trabalhar diretamente com as funções, consulte as subsecções seguintes para saber como as importar independentemente.

Caixas de escala

Ao dimensionar uma imagem para cima ou para baixo, pode dimensionar adequadamente as coordenadas da caixa delimitadora correspondente para corresponder 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)
# >>> 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 as coordenadas da caixa delimitadora do formato (x1, y1, x2, y2) para o formato (x, y, largura, altura), em que (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

Veja a documentação de cada função ou visite a página ultralytics.utils.ops página de referência para ler mais.

Plotagem

Anotações de desenho

Ultralytics inclui um Annotator para anotar vários tipos de dados. É melhor utilizada com caixas delimitadoras de deteção de objectos, pontos-chave da posee caixas delimitadoras orientadas.

Ultralytics Anotação de varrimento

Exemplos Python utilizando o Ultralytics YOLO 🚀

import cv2

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="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 = SolutionAnnotator(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.

Caixas delimitadoras horizontais

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 utilizados a partir de model.names quando trabalhar com resultados de deteção.

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

Caixas de contorno Anotação de círculo Etiqueta de círculo



Ver: Guia detalhado para anotações de texto e círculos com Python Demonstrações em direto | Ultralytics Anotações 🚀

import cv2

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

model = YOLO("yolo11s.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)
    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)], color=colors(cls, True))

    writer.write(im0)
    cv2.imshow("Ultralytics circle annotation", im0)

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

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

Caixas de contorno Anotação de texto Etiqueta de texto

import cv2

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

model = YOLO("yolo11s.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 text 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)
    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)], color=colors(cls, True))

    writer.write(im0)
    cv2.imshow("Ultralytics text annotation", im0)

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

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

Ver o Annotator Página de referência para mais informações.

Diversos

Perfilamento de código

Verificar a duração da execução/processamento do código utilizando with ou 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 suportados

Precisa de utilizar de forma programática os formatos de imagem ou vídeo suportados no Ultralytics? Utilize estas constantes, se necessário:

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

Tornar divisível

Calcular o número inteiro mais próximo de x que é divisível equitativamente 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 melhorar os fluxos de trabalho de aprendizagem automática?

O pacote Ultralytics inclui utilitários concebidos para simplificar e otimizar os fluxos de trabalho de aprendizagem automática. Os principais utilitários incluem a anotação automática para rotular conjuntos de dados, converter o formato COCO para YOLO com convert_coco, comprimir imagens e dividir automaticamente o conjunto de dados. Essas ferramentas reduzem o esforço manual, garantem a consistência e aumentam a eficiência do processamento de dados.

Como é que posso utilizar Ultralytics para etiquetar automaticamente o meu conjunto de dados?

Se tiver um modelo de deteção de objectos pré-treinado em Ultralytics YOLO , pode utilizá-lo com o modelo SAM para anotar automaticamente o seu conjunto de dados em formato de segmentação. Aqui está um exemplo:

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 mais informações, consulte a secção de referência auto_annotate.

Como é que converto as anotações do conjunto de dados COCO para o formato YOLO em Ultralytics?

Para converter as anotações COCO JSON no formato YOLO para deteção de objectos, pode utilizar o convert_coco utilitário. Aqui está um exemplo de trecho de código:

from ultralytics.data.converter import convert_coco

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

Para mais informações, visite a página de referência do convert_coco.

Qual é o objetivo do explorador de dados YOLO no pacote Ultralytics ?

O YOLO Explorador é uma ferramenta poderosa introduzida no 8.1.0 para melhorar a compreensão do conjunto de dados. Permite-lhe utilizar consultas de texto para encontrar instâncias de objectos no seu conjunto de dados, facilitando a análise e a gestão dos seus dados. Esta ferramenta fornece informações valiosas sobre a composição e distribuição do conjunto de dados, ajudando a melhorar a formação e o desempenho do modelo.

Como é que posso converter caixas delimitadoras em segmentos em Ultralytics?

Para converter dados de caixa delimitadora existentes (em x y w h ) para segmentos, é possível utilizar o yolo_bbox2segment função. Certifique-se de que os seus ficheiros estão organizados com diretórios separados para imagens e 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 obter mais informações, visite a página de referênciayolo_bbox2segment.

📅C riado há 1 ano ✏️ Atualizado há 5 dias

Comentários