Перейти к содержанию

Простые утилиты

код с перспективой

Сайт ultralytics Пакет поставляется с огромным количеством утилит, которые могут поддержать, улучшить и ускорить ваши рабочие процессы. Существует множество других, но вот некоторые из них, которые будут полезны для большинства разработчиков. Они также являются отличным ориентиром при изучении программирования.



Смотреть: Ultralytics Утилиты | Автоматическая аннотация, API проводника и преобразование наборов данных

Данные

Автоматическая маркировка / аннотации

Аннотирование массивов данных - очень ресурсоемкий и трудоемкий процесс. Если у вас есть модельобнаружения объектов YOLO , обученная на достаточном количестве данных, вы можете использовать ее и SAM для автоаннотирования дополнительных данных (формат сегментации).

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",
)
  1. Из этой функции ничего не возвращается

  2. См. справочный раздел для annotator.auto_annotate для получения более подробной информации о работе этой функции.

  3. Используйте в сочетании с функция segments2boxes для создания ограничивающих рамок для обнаружения объектов, а также

Преобразование масок сегментации в формат YOLO

Маски сегментации в формате YOLO

Используется для преобразования набора данных изображений масок сегментации в формат YOLO формат сегментации. Эта функция получает каталог, содержащий изображения масок в двоичном формате, и преобразует их в формат сегментации YOLO .

Преобразованные маски будут сохранены в указанном каталоге вывода.

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)

Преобразование COCO в формат YOLO

Используется для преобразования аннотаций COCO JSON в надлежащий формат YOLO . Для наборов данных по обнаружению объектов (bounding box), use_segments и use_keypoints должны быть False

from ultralytics.data.converter import convert_coco

convert_coco(  # (1)!
    "../datasets/coco/annotations/",
    use_segments=False,
    use_keypoints=False,
    cls91to80=True,
)
  1. Из этой функции ничего не возвращается

Для получения дополнительной информации о convert_coco функция, посетить справочную страницу

Получить размеры ограничительной рамки

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

Преобразование ограничительных рамок в сегменты

С существующими x y w h данные о границах, преобразуйте их в сегменты с помощью yolo_bbox2segment функция. Файлы для изображений и аннотаций должны быть организованы следующим образом:

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. Из этой функции ничего не возвращается

Посетите yolo_bbox2segment справочная страница для получения дополнительной информации об этой функции.

Преобразование сегментов в ограничительные рамки

Если у вас есть набор данных, в котором используется формат набора данных сегментации вы можете легко преобразовать их в ограничительные рамки, расположенные вверх-вправо (или по горизонтали) (x y w h формат) с помощью этой функции.

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

Чтобы понять, как работает эта функция, посетите справочную страницу

Утилиты

Сжатие изображений

Сжимает один файл изображения до уменьшенного размера с сохранением соотношения сторон и качества. Если размер входного изображения меньше максимального, оно не будет изменено.

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. Из этой функции ничего не возвращается

Автоматическое разделение набора данных

Автоматическое разбиение набора данных на train/val/test расщепления и сохраните полученные расщепления в autosplit_*.txt файлы. Эта функция использует случайную выборку, которая не включается при использовании fraction аргумент в пользу обучения.

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, 2] с N как количество (x, y) точки, определяющие контур многоугольника.

Внимание

N всегда должен быть ровным.

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

Ограничивающие рамки

Экземпляры граничной коробки (горизонтальной)

Для управления данными ограничительных рамок используется Bboxes Класс поможет преобразовать формат координат бокса, масштабировать размеры бокса, вычислять площади, включать смещения и многое другое!

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]]
# )

См. Bboxes справочный раздел для получения дополнительной информации о доступных атрибутах и методах.

Наконечник

Доступ ко многим из перечисленных ниже функций (и не только) можно получить с помощью Bboxes класс но если вы предпочитаете работать с функциями напрямую, смотрите следующие подразделы о том, как импортировать их независимо.

Масштабные ящики

При масштабировании изображения вверх или вниз соответствующие координаты ограничительной рамки могут быть соответствующим образом изменены с помощью 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. Граничные поля, масштабированные для нового размера изображения

Преобразования формата ограничительной рамки

XYXY → XYWH

Преобразуйте координаты ограничительной рамки из формата (x1, y1, x2, y2) в формат (x, y, width, height), где (x1, y1) - это левый верхний угол, а (x2, y2) - правый нижний угол.

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]]
# )

Все преобразования граничной коробки

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

См. docstring для каждой функции или посетите ultralytics.utils.ops справочная страница чтобы узнать больше о каждой функции.

Черчение

Рисование аннотаций

Ultralytics включает класс Annotator, который можно использовать для аннотирования любых данных. Легче всего использовать его с ограничительными рамками для обнаружения объектов, ключевыми точками позиционирования и ориентированными ограничительными рамками.

Ultralytics Аннотация

Python Примеры использования 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.

Горизонтальные ограничительные рамки

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. Можно использовать имена из model.names когда работа с результатами обнаружения

Ориентированные граничные коробки (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()

Ограничительные рамки Круговая аннотация Круговая метка



Смотреть: Подробное руководство по текстовым и круговым аннотациям с живыми демонстрациями Python | Ultralytics Аннотации 🚀.

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

Ограничительные рамки Текстовая аннотация Текстовая метка

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

См. Annotator Справочная страница для получения дополнительных сведений.

Разное

Профилирование кода

Проверьте продолжительность выполнения/обработки кода, используя with или в качестве декоратора.

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 Поддерживаемые форматы

Хотите или хотите программно использовать форматы изображений или видео, поддерживаемые Ultralytics ? Используйте эти константы, если вам это необходимо.

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

Сделать делимым

Вычисляет ближайшее целое число к x сделать равномерно делимым при делении на y.

from ultralytics.utils.ops import make_divisible

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

ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ

Какие утилиты включены в пакет Ultralytics для улучшения рабочих процессов машинного обучения?

Пакет Ultralytics включает в себя множество утилит, предназначенных для оптимизации рабочих процессов машинного обучения. Среди основных утилит - автоаннотирование для маркировки наборов данных, преобразование COCO в формат YOLO с помощью convert_coco, сжатие изображений и автоматическое разделение наборов данных. Эти инструменты направлены на сокращение ручного труда, обеспечение согласованности и повышение эффективности обработки данных.

Как использовать Ultralytics для авторазметки набора данных?

Если у вас есть предварительно обученная модель обнаружения объектов Ultralytics YOLO , вы можете использовать ее вместе с SAM для автоаннотирования набора данных в формате сегментации. Вот пример:

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

Для получения более подробной информации обратитесь к справочному разделу auto_annotate.

Как преобразовать аннотации наборов данных COCO в формат YOLO в программе Ultralytics?

Чтобы преобразовать аннотации COCO JSON в формат YOLO для обнаружения объектов, вы можете использовать convert_coco утилита. Вот пример фрагмента кода:

from ultralytics.data.converter import convert_coco

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

Дополнительную информацию можно найти на справочной странице convert_coco.

Каково назначение YOLO Data Explorer в пакете Ultralytics ?

Сайт YOLO Исследователь это мощный инструмент, представленный в 8.1.0 обновление для улучшения понимания набора данных. Он позволяет использовать текстовые запросы для поиска экземпляров объектов в наборе данных, что упрощает анализ и управление данными. Этот инструмент дает ценные сведения о составе и распределении наборов данных, помогая улучшить обучение и производительность моделей.

Как преобразовать ограничивающие рамки в сегменты в Ultralytics?

Чтобы преобразовать существующие данные ограничительных рамок (в x y w h формат) в сегменты, вы можете использовать yolo_bbox2segment функция. Убедитесь, что ваши файлы организованы с отдельными каталогами для изображений и этикеток.

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

Для получения дополнительной информации посетите справочную страницуyolo_bbox2segment.

📅 Created 9 months ago ✏️ Updated 15 days ago

Комментарии