간단한 유틸리티#
ultralytics 패키지는 워크플로를 지원하고 개선하며 가속하는 다양한 유틸리티를 제공합니다. 사용할 수 있는 유틸리티는 더 많지만, 이 가이드에서는 개발자에게 유용한 몇 가지를 소개하고 Ultralytics 도구를 활용한 프로그래밍의 실용적인 참고 자료를 제공합니다.
시청: Ultralytics 유틸리티 | 자동 주석, Explorer API 및 데이터셋 변환
데이터#
자동 라벨링 / 주석#
데이터셋 주석은 리소스와 시간이 많이 소요되는 작업입니다. 적절한 양의 데이터로 학습한 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",
)이 함수는 값을 반환하지 않습니다. 자세한 내용은 다음을 참조하세요.
- 함수 작동 방식에 대한 자세한 내용은
annotator.auto_annotate참고 섹션을 참조하세요. - 객체 감지 바운딩 박스도 생성하려면
segments2boxes함수와 함께 사용하세요.
데이터셋 주석 시각화#
이 함수는 학습 전에 이미지의 YOLO 주석을 시각화하여 잘못된 감지 결과를 초래할 수 있는 주석 오류를 식별하고 수정하도록 돕습니다. 바운딩 박스를 그리고, 클래스 이름으로 객체에 레이블을 지정하며, 가독성을 높이기 위해 배경의 휘도에 따라 텍스트 색상을 조정합니다.
from ultralytics.data.utils import visualize_image_annotations
label_map = { # 주석이 지정된 모든 클래스 레이블을 포함하는 레이블 맵을 정의합니다.
0: "person",
1: "car",
}
# Visualize
visualize_image_annotations(
"path/to/image.jpg", # 입력 이미지 경로입니다.
"path/to/annotations.txt", # 이미지의 주석 파일 경로입니다.
label_map,
)세그멘테이션 마스크를 YOLO 형식으로 변환#

세그멘테이션 마스크 이미지 데이터셋을 Ultralytics YOLO 세그멘테이션 형식으로 변환할 때 사용합니다. 이 함수는 바이너리 형식의 마스크 이미지가 포함된 디렉터리를 입력받아 YOLO 세그멘테이션 형식으로 변환합니다.
변환된 마스크는 지정된 출력 디렉터리에 저장됩니다.
from ultralytics.data.converter import convert_segment_masks_to_yolo_seg
# `classes`는 데이터셋에 포함된 전체 클래스 수입니다.
# COCO 데이터셋에는 클래스가 80개 있습니다.
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_segments과 use_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.txtfrom ultralytics.data.converter import yolo_bbox2segment
yolo_bbox2segment(
im_dir="path/to/images",
save_dir=None, # 이미지 디렉터리 옆의 "labels-segment"에 저장됨
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, 812, 402, 808, 714, 808, 392],
[115, 398, 113, 400, 150, 410, 150, 400, 149, 298],
[267, 412, 265, 413, 300, 420, 300, 413, 299, 412],
],
dtype=np.float32,
)
segments2boxes([s.reshape(-1, 2) for s in segments])
# >>> array([[804.5, 553. , 15. , 322. ],
# [131.5, 354. , 37. , 112. ],
# [282.5, 416. , 35. , 8. ]],
# dtype=float32) # xywh 바운딩 박스이 함수의 작동 방식을 알아보려면 참고 페이지를 참조하세요.
유틸리티#
이미지 압축#
가로 세로 비율과 품질을 유지하면서 단일 이미지 파일의 크기를 줄입니다. 입력 이미지가 최대 크기보다 작으면 크기를 조정하지 않습니다.
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), # (학습, 검증, 테스트) 분할 비율
annotated_only=False, # True인 경우 주석 파일이 있는 이미지만 분할
)이 함수에 대한 자세한 내용은 참고 페이지를 참조하세요.
세그먼트 폴리곤을 바이너리 마스크로 변환#
단일 폴리곤(리스트 형식)을 지정된 이미지 크기의 바이너리 마스크로 변환합니다. 폴리곤은 폴리곤 윤곽을 정의하는 x, y 값이 번갈아 나열된 N 좌표의 1D 평탄 배열이어야 합니다.
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]) # (N,) 평탄한 x, y 좌표
mask = polygon2mask(
imgsz, # tuple
[polygon], # 리스트로 입력
color=255, # 8비트 바이너리
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), # 원본 이미지 크기
boxes=xyxy_boxes, # 원본 이미지의 박스
img0_shape=(new_h, new_w), # 크기를 조정할 이미지 크기
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, 너비, 높이) 형식으로 변환합니다. 여기서 (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 → 왼쪽 위 모서리, w, h
xywh2xyxy,
xywhn2xyxy, # 정규화 좌표 → 픽셀
xyxy2ltwh, # xyxy → 왼쪽 위 모서리, w, h
xyxy2xywhn, # 픽셀 → 정규화 좌표
)
for func in (ltwh2xywh, ltwh2xyxy, xywh2ltwh, xywh2xyxy, xywhn2xyxy, xyxy2ltwh, xyxy2xywhn):
print(help(func)) # 함수 독스트링 출력자세한 내용은 각 함수의 독스트링을 확인하거나 ultralytics.utils.ops 참고 페이지를 참조하세요.
플로팅#
주석 유틸리티#
Ultralytics에는 다양한 데이터 유형에 주석을 추가할 수 있는 Annotator 클래스가 포함되어 있습니다. 이 클래스는 객체 감지 바운딩 박스, 포즈 키포인트, 방향 바운딩 박스에 사용하는 것이 가장 적합합니다.
박스 주석#
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()감지 결과를 처리할 때 model.names의 이름을 사용할 수 있습니다. 자세한 내용은 Annotator 참고 페이지도 참조하세요.
Ultralytics 스윕 주석#
import sys
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.")
sys.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 메서드에 대한 자세한 내용은 참고 섹션의 여기에서 확인하세요.
적응형 레이블 주석#
SolutionAnnotator.adaptive_label은 shape 인수로 모양을 지정하는 레이블을 그립니다(이 인수는 이전의 circle_label 및 text_label 메서드를 대체합니다).
- 사각형:
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")
시청: Python 라이브 데모로 알아보는 텍스트 및 원형 주석 심층 가이드 | 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 # 측정할 작업
print(dt)
# >>> "경과 시간은 9.5367431640625e-07초입니다"Ultralytics 지원 형식#
Ultralytics에서 지원하는 이미지 또는 동영상 형식을 프로그래밍 방식으로 사용해야 하나요? 필요한 경우 다음 상수를 사용하세요:
from ultralytics.data.utils import IMG_FORMATS, VID_FORMATS
print(IMG_FORMATS)
# {'avif', 'bmp', 'dng', 'heic', 'heif', 'jp2', 'jpeg', 'jpg', 'mpo', 'png', 'tif', 'tiff', 'webp'}
print(VID_FORMATS)
# {'asf', 'avi', 'gif', 'm4v', 'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'ts', 'wmv', 'webm'}배수로 만들기#
x 이상이면서 y로 나누어떨어지는 가장 작은 정수를 계산합니다.
from ultralytics.utils.ops import make_divisible
make_divisible(7, 3)
# >>> 9
make_divisible(7, 2)
# >>> 8자주 묻는 질문#
Ultralytics 패키지에는 머신러닝 워크플로를 간소화하고 최적화하도록 설계된 유틸리티가 포함되어 있습니다. 주요 유틸리티에는 데이터셋 레이블링을 위한 자동 어노테이션, COCO를 YOLO 형식으로 변환하는 convert_coco, 이미지 압축, 데이터셋 자동 분할이 있습니다. 이러한 도구는 수작업을 줄이고 일관성을 보장하며 데이터 처리 효율을 높입니다.
사전 학습된 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", )자세한 내용은 auto_annotate 참조 섹션을 확인하거나, 코드 작성 없이 호스팅 방식으로 사용할 수 있는 대안인 Ultralytics Platform을 이용하세요. SAM 2.1, SAM 3 또는 SAM 3.1을 사용한 클릭 기반 마스킹이나, 감지, 세그멘테이션, OBB 작업을 위한 사전 학습 및 파인튜닝된 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 히트맵을 확인하여 학습 전에 불균형과 이상치를 파악할 수 있습니다.기존 바운딩 박스 데이터(
x y w h형식)를 세그먼트로 변환하려면yolo_bbox2segment함수를 사용할 수 있습니다. 이미지와 레이블을 별도의 디렉터리에 정리해야 합니다.from ultralytics.data.converter import yolo_bbox2segment yolo_bbox2segment( im_dir="path/to/images", save_dir=None, # 이미지 디렉터리 옆의 "labels-segment"에 저장됨 sam_model="sam_b.pt", )자세한 내용은 yolo_bbox2segment 참조 페이지를 확인하세요.