간편 유틸리티

YOLO model code with 3D perspective visualization

ultralytics 패키지는 사용자의 워크플로우를 지원, 강화 및 가속화하기 위한 다양한 유틸리티를 제공합니다. 사용 가능한 유틸리티는 훨씬 더 많지만, 이 가이드에서는 개발자에게 가장 유용한 도구들을 소개하며 Ultralytics 도구를 활용한 프로그래밍을 위한 실용적인 참고 자료 역할을 합니다.



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

데이터

자동 라벨링 / 주석(Annotation)

데이터셋 주석은 리소스를 많이 소모하고 시간이 걸리는 과정입니다. 적절한 양의 데이터로 훈련된 Ultralytics YOLO 객체 탐지 모델이 있다면, 이 모델을 SAM과 함께 사용하여 세그멘테이션 형식으로 추가 데이터를 자동 주석 처리할 수 있습니다.

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

이 함수는 값을 반환하지 않습니다. 자세한 내용은 다음을 참조하십시오:

데이터셋 주석 시각화

이 함수는 훈련 전 이미지에서 YOLO 주석을 시각화하여, 잘못된 탐지 결과로 이어질 수 있는 오류 주석을 식별하고 수정하도록 돕습니다. 바운딩 박스를 그리고, 클래스 이름으로 객체에 라벨을 붙이며, 배경의 휘도에 따라 텍스트 색상을 조정하여 가독성을 높입니다.

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

세그멘테이션 마스크를 YOLO 형식으로 변환

세그멘테이션 마스크에서 YOLO 형식으로

이 기능을 사용하여 세그멘테이션 마스크 이미지 데이터셋을 Ultralytics 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 형식으로 변환하십시오. 객체 탐지(바운딩 박스) 데이터셋의 경우, use_segmentsuse_keypoints를 모두 False로 설정하십시오.

from ultralytics.data.converter import convert_coco

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

convert_coco 함수에 대한 추가 정보는 참조 페이지를 방문하십시오.

바운딩 박스 크기 가져오기

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

바운딩 박스를 세그먼트로 변환

기존의 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(
    im_dir="path/to/images",
    save_dir=None,  # saved to "labels-segment" in images directory
    sam_model="sam_b.pt",
)

함수에 대한 자세한 내용은 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)

데이터셋 자동 분할

데이터셋을 train/val/test로 자동 분할하고 그 결과를 autosplit_*.txt 파일로 저장하십시오. 이 함수는 무작위 샘플링을 사용하며, 훈련을 위한 fraction 인수를 사용할 때는 제외됩니다.

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
)

이 함수에 대한 추가 세부 사항은 참조 페이지를 확인하십시오.

세그먼트 폴리곤을 이진 마스크로 변환

단일 폴리곤(리스트 형태)을 지정된 이미지 크기의 이진 마스크로 변환하십시오. 폴리곤은 [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)
# >>> 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]]
# )

바운딩 박스 형식 변환

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

각 함수의 독스트링을 보거나 ultralytics.utils.ops 참조 페이지를 방문하여 자세한 내용을 읽어보십시오.

플로팅(Plotting)

주석 유틸리티

Ultralytics는 다양한 데이터 유형을 주석 처리하기 위한 Annotator 클래스를 포함합니다. 이는 객체 탐지 바운딩 박스, 포즈 키포인트회전된 바운딩 박스와 함께 사용할 때 가장 좋습니다.

박스 주석

Ultralytics YOLO를 사용하는 Python 예제 🚀
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()

Names can be used from model.names when working with detection results. Also see the Annotator Reference Page for additional insight.

Ultralytics 스윕 주석

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

sweep_annotator 메서드에 대한 자세한 내용은 여기의 참조 섹션에서 찾을 수 있습니다.

적응형 라벨 주석

경고

Ultralytics v8.3.167부터 circle_labeltext_label은 통합된 adaptive_label 함수로 대체되었습니다. 이제 shape 인수를 사용하여 주석 유형을 지정할 수 있습니다:

  • 사각형: annotator.adaptive_label(box, label=names[int(cls)], color=colors(cls, True), shape="rect")
  • 원형: 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 🚀
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()

추가적인 통찰력을 얻으려면 SolutionAnnotator 참조 페이지를 참조하십시오.

기타

코드 프로파일링

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)
# {'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'}

나눗셈 가능하게 만들기

Calculate the nearest whole number to x that is evenly divisible by y.

from ultralytics.utils.ops import make_divisible

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

FAQ

머신러닝 워크플로우를 강화하기 위해 Ultralytics 패키지에 포함된 유틸리티는 무엇인가요?

The Ultralytics package includes utilities designed to streamline and optimize machine learning workflows. Key utilities include auto-annotation for labeling datasets, converting COCO to YOLO format with convert_coco, compressing images, and dataset auto-splitting. These tools reduce manual effort, ensure consistency, and enhance data processing efficiency.

Ultralytics를 사용하여 데이터셋을 자동 라벨링하려면 어떻게 해야 하나요?

사전 훈련된 Ultralytics YOLO 객체 탐지 모델이 있다면, 이를 SAM 모델과 함께 사용하여 데이터셋을 세그멘테이션 형식으로 자동 주석 처리할 수 있습니다. 예시는 다음과 같습니다:

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

For more details, check the auto_annotate reference section, or use Ultralytics Platform as a hosted, no-code alternative with click-based masking via SAM 2.1 or SAM 3, or predictions from pretrained and fine-tuned YOLO models for detect, segment, and OBB tasks.

Ultralytics에서 COCO 데이터셋 주석을 YOLO 형식으로 어떻게 변환하나요?

COCO JSON 주석을 객체 탐지를 위한 YOLO 형식으로 변환하려면 convert_coco 유틸리티를 사용할 수 있습니다. 다음은 샘플 코드 스니펫입니다:

from ultralytics.data.converter import convert_coco

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

추가 정보를 보려면 convert_coco 참조 페이지를 방문하십시오.

데이터셋 구성과 분포를 분석하려면 어떻게 해야 하나요?

Ultralytics Platform은 자동 데이터셋 분석을 제공합니다. Charts 탭은 분할 분포, 상위 클래스 수, 이미지 차원 히스토그램 및 주석 위치의 2D 히트맵을 표시하여 훈련 전에 불균형과 이상치를 파악하도록 돕습니다.

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 참조 페이지를 방문하십시오.

댓글