Salta para o conteúdo

Utilitários simples

código com perspetiva

O ultralytics vem com uma miríade de utilitários que podem apoiar, melhorar e acelerar os teus fluxos de trabalho. Existem muitos mais disponíveis, mas aqui estão alguns que serão úteis para a maioria dos programadores. São também um ótimo ponto de referência para usares quando estiveres a aprender a programar.



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

Dados

YOLO Explorador de dados

YOLO Explorador foi adicionado no 8.1.0 é uma ferramenta poderosa que pode utilizar para compreender melhor o seu conjunto de dados. Uma das principais funções que o YOLO Explorer fornece é a capacidade de utilizar consultas de texto para encontrar instâncias de objectos no seu conjunto de dados.

Etiquetagem automática / Anotações

A anotação de conjuntos de dados é um processo que consome muitos recursos e tempo. Se tiveres um modelo de deteção de objectos YOLO treinado com uma quantidade razoável de dados, podes utilizá-lo e SAM para anotar automaticamente dados adicionais (formato de segmentação).

from ultralytics.data.annotator import auto_annotate

auto_annotate(  # (1)!
    data="path/to/new/data",
    det_model="yolov8n.pt",
    sam_model="mobile_sam.pt",
    device="cuda",
    output_dir="path/to/save_labels",
)
  1. Não devolve nada desta função

  2. Consulta a secção de referência para annotator.auto_annotate para saberes mais sobre o funcionamento da função.

  3. Utiliza em combinação com o função segments2boxes para gerar caixas delimitadoras de deteção de objectos, bem como

Converte COCO para o formato YOLO

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

from ultralytics.data.converter import convert_coco

convert_coco(  # (1)!
    "../datasets/coco/annotations/",
    use_segments=False,
    use_keypoints=False,
    cls91to80=True,
)
  1. Não devolve nada desta função

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

Obtém as dimensões da caixa delimitadora

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

model = YOLO('yolov8n.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()))

Converter caixas delimitadoras em segmentos

Com os actuais x y w h dados da caixa delimitadora, converte para segmentos utilizando o yolo_bbox2segment Funciona. Os ficheiros para imagens e anotações têm de ser organizados desta 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(  # (1)!
    im_dir="path/to/images",
    save_dir=None,  # saved to "labels-segment" in images directory
    sam_model="sam_b.pt",
)
  1. Não devolve nada desta função

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

Converter segmentos em caixas delimitadoras

Se tiveres um conjunto de dados que utilize o formato do conjunto de dados de segmentação podes facilmente convertê-las em caixas delimitadoras para cima e para a direita (ou horizontais) (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 compreenderes o funcionamento desta função, visita a página de referência

Utilidades

Compressão de imagens

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)  # (1)!
  1. Não devolve nada desta função

Auto-split Dataset

Divide automaticamente um conjunto de dados em train/val/test divide e guarda as divisões resultantes em autosplit_*.txt ficheiros. Esta função utiliza a amostragem aleatória, que não está incluída quando utilizas fraction argumento para a formação.

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
)
  1. Não devolve nada desta função

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

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

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

Aviso

N deves sempre fica equilibrado.

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, a função Bboxes A classe ajuda-te a converter entre formatação 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]]
# )

Vê o Bboxes secção de referência para conheceres mais atributos e métodos disponíveis.

Dica

Muitas das seguintes funções (e mais) podem ser acedidas utilizando a função Bboxes classe mas se preferires trabalhar com as funções diretamente, vê nas próximas subsecções como importá-las independentemente.

Caixas de escala

Ao aumentar ou diminuir a escala de uma imagem, as coordenadas da caixa delimitadora correspondentes podem ser adequadamente dimensionadas 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)  # (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]]
# )
  1. Caixas de contorno escaladas para o novo tamanho de imagem

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
)

Vê a documentação de cada função ou visita a página ultralytics.utils.ops página de referência para leres mais sobre cada função.

Traçar

Anotações de desenho

Ultralytics inclui uma classe Annotator que pode ser utilizada para anotar qualquer tipo de dados. É mais fácil de utilizar com caixas delimitadoras de deteção de objectos, pontos-chave de pose e caixas delimitadoras orientadas.

Caixas de limite horizontais

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()
  1. 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()

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

Diversos

Perfil do código

Verifica a duração do código a executar/processar 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

Queres ou precisas de utilizar os formatos dos tipos de imagens ou vídeos suportados por Ultralytics de forma programática? Utiliza estas constantes se precisares.

from ultralytics.data.utils import IMG_FORMATS, VID_FORMATS

print(IMG_FORMATS)
# >>> ('bmp', 'dng', 'jpeg', 'jpg', 'mpo', 'png', 'tif', 'tiff', 'webp', 'pfm')

Torna-o divisível

Calcula o número inteiro mais próximo de x para tornar divisível por igual quando dividido por y.

from ultralytics.utils.ops import make_divisible

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


Criado em 2024-02-20, Atualizado em 2024-05-19
Autores: glenn-jocher (5), RizwanMunawar (1), Burhan-Q (2)

Comentários