κ°λ¨ν μ νΈλ¦¬ν°
κ·Έλ¦¬κ³ ultralytics
ν¨ν€μ§μλ μν¬νλ‘λ₯Ό μ§μ, κ°μ λ° μλλ₯Ό λμΌ μ μλ μλ§μ μ νΈλ¦¬ν°κ° ν¬ν¨λμ΄ μμ΅λλ€. λ λ§μ μ νΈλ¦¬ν°κ° μμ§λ§ μ¬κΈ°μλ λλΆλΆμ κ°λ°μμκ² μ μ©ν λͺ κ°μ§λ₯Ό μκ°ν©λλ€. λν νλ‘κ·Έλλ°μ λ°°μΈ λ μ°Έκ³ ν μ μλ νλ₯ν μ°Έκ³ μλ£μ΄κΈ°λ ν©λλ€.
Watch: Ultralytics μ νΈλ¦¬ν° > μλ μ£Όμ, νμκΈ° API λ° λ°μ΄ν° μΈνΈ λ³ν
λ°μ΄ν°
YOLO λ°μ΄ν° νμκΈ°
YOLO νμκΈ° μ μΆκ°λμμ΅λλ€. 8.1.0
1μ£Όλ
κΈ°λ
μ
λ°μ΄νΈλ‘, λ°μ΄ν° μ§ν©μ λ μ μ΄ν΄νλ λ° μ¬μ©ν μ μλ κ°λ ₯ν λꡬμ
λλ€. YOLO Explorerκ° μ 곡νλ μ£Όμ κΈ°λ₯ μ€ νλλ ν
μ€νΈ 쿼리λ₯Ό μ¬μ©νμ¬ λ°μ΄ν° μ§ν©μμ κ°μ²΄ μΈμ€ν΄μ€λ₯Ό μ°Ύμ μ μλ κΈ°λ₯μ
λλ€.
μλ λΌλ²¨λ§/μ£Όμ
λ°μ΄ν° μΈνΈ μ΄λ Έν μ΄μ μ 리μμ€μ μκ°μ΄ λ§μ΄ μμλλ νλ‘μΈμ€μ λλ€. μ μ ν μμ λ°μ΄ν°λ‘ νμ΅λ YOLO κ°μ²΄ κ°μ§ λͺ¨λΈμ΄ μλ κ²½μ°, μ΄λ₯Ό μ¬μ©νκ³ SAM λ₯Ό μ¬μ©νμ¬ μΆκ° λ°μ΄ν°(μΈλΆν νμ)μ μλ μ£Όμμ λ¬ μ μμ΅λλ€.
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",
)
-
μ΄ ν¨μμμ λ°νλλ κ²μ μμ΅λλ€.
-
λ€μμ λν μ°Έμ‘° μΉμ μ μ°Έμ‘°νμμμ€.
annotator.auto_annotate
λ₯Ό μ°Έμ‘°νμ¬ κΈ°λ₯ μλ λ°©μμ λν΄ μμΈν μμ보μΈμ. -
μ ν¨κ» μ¬μ© ν¨μ
segments2boxes
λ₯Ό μ¬μ©νμ¬ κ°μ²΄ κ°μ§ κ²½κ³ μμλ μμ±ν μ μμ΅λλ€.
COCOλ₯Ό YOLO νμμΌλ‘ λ³ν
COCO JSON μ£Όμμ μ μ ν YOLO νμμΌλ‘ λ³ννλ λ° μ¬μ©ν©λλ€. κ°μ²΄ κ°μ§(λ°μ΄λ© λ°μ€) λ°μ΄ν° μΈνΈμ κ²½μ°, 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,
)
- μ΄ ν¨μμμ λ°νλλ κ²μ μμ΅λλ€.
μ λν μμΈν λ΄μ©μ convert_coco
ν¨μμ
λλ€, μ°Έμ‘° νμ΄μ§ λ°©λ¬Έ
λ°μ΄λ© λ°μ€ μΉμ κ°μ Έμ€κΈ°
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()))
λ°μ΄λ© λ°μ€λ₯Ό μΈκ·Έλ¨ΌνΈλ‘ λ³ννκΈ°
κΈ°μ‘΄ 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"
)
- μ΄ ν¨μμμ λ°νλλ κ²μ μμ΅λλ€.
λ°©λ¬ΈνκΈ° yolo_bbox2segment
μ°Έμ‘° νμ΄μ§ κΈ°λ₯μ λν μμΈν λ΄μ©μ νμΈνμΈμ.
μΈκ·Έλ¨ΌνΈλ₯Ό λ°μ΄λ© λ°μ€λ‘ λ³ννκΈ°
λ₯Ό μ¬μ©νλ λ°μ΄ν° μ§ν©μ΄ μλ κ²½μ° μΈλΆν λ°μ΄ν° μΈνΈ νμ λ₯Ό μ¬μ©νλ©΄ μ½κ² μμ§(λλ μν) κ²½κ³ μμλ‘ λ³νν μ μμ΅λλ€(x y w h
νμ)μ μ¬μ©νμ¬ μ΄ ν¨μλ₯Ό μ¬μ©ν μ μμ΅λλ€.
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)!
- μ΄ ν¨μμμ λ°νλλ κ²μ μμ΅λλ€.
λ°μ΄ν° μΈνΈ μλ λΆν
λ°μ΄ν° μ§ν©μ λ€μκ³Ό κ°μ΄ μλμΌλ‘ λΆν ν©λλ€. 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
)
- μ΄ ν¨μμμ λ°νλλ κ²μ μμ΅λλ€.
μ΄ κΈ°λ₯μ λν μμΈν λ΄μ©μ μ°Έμ‘° νμ΄μ§λ₯Ό μ°Έμ‘°νμΈμ.
μΈκ·Έλ¨ΌνΈ λ€κ°νμ λ°μ΄λ리 λ§μ€ν¬λ‘ λ³ννκΈ°
λ¨μΌ λ€κ°ν(λͺ©λ‘)μ μ§μ λ μ΄λ―Έμ§ ν¬κΈ°μ μ΄μ§ λ§μ€ν¬λ‘ λ³νν©λλ€. λ€μκ³Ό κ°μ ννμ λ€κ°ν [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
ν΄λμ€λ μμ μ’ν μμ λ³ν, μμ ν¬κΈ° μ‘°μ , λ©΄μ κ³μ°, μ€νμ
ν¬ν¨ λ±μ μμ
μ λμμ€λλ€!
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")
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,
)
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]]
)
- μ μ΄λ―Έμ§ ν¬κΈ°μ λ§κ² ν¬κΈ°κ° μ‘°μ λ λ°μ΄λ© λ°μ€
λ°μ΄λ© λ°μ€ νμ λ³ν
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)
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 xywh2xyxy
from ultralytics.utils.ops import xywhn2xyxy # normalized β pixel
from ultralytics.utils.ops import xyxy2xywhn # pixel β normalized
from ultralytics.utils.ops import xywh2ltwh # xywh β top-left corner, w, h
from ultralytics.utils.ops import xyxy2ltwh # xyxy β top-left corner, w, h
from ultralytics.utils.ops import ltwh2xywh
from ultralytics.utils.ops import ltwh2xyxy
κ° κΈ°λ₯μ λν λ¬Έμ λ¬Έμμ΄μ μ°Έμ‘°νκ±°λ ultralytics.utils.ops
μ°Έμ‘° νμ΄μ§ λ₯Ό ν΄λ¦νμ¬ κ° κΈ°λ₯μ λν΄ μμΈν μμ보μΈμ.
νλ‘ν
λλ‘μ μ£Όμ
Ultralytics μλ λͺ¨λ μ’ λ₯μ λ°μ΄ν°μ μ£Όμμ λ€λ λ° μ¬μ©ν μ μλ Annotator ν΄λμ€κ° ν¬ν¨λμ΄ μμ΅λλ€. κ°μ²΄ κ°μ§ λ°μ΄λ© λ°μ€, ν¬μ¦ ν€ ν¬μΈνΈ, λ°©ν₯μ± λ°μ΄λ© λ°μ€μ κ°μ₯ μ½κ² μ¬μ©ν μ μμ΅λλ€.
μν λ°μ΄λ© λ°μ€
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()
- μ΄λ¦μ λ€μμμ μ¬μ©ν μ μμ΅λλ€.
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"{names.get(int(c_idx))}"
ann.box_label(
obb,
label,
color=colors(c_idx, True),
rotated=True,
)
image_with_obb = ann.result()
μ°Έμ‘° Annotator
μ°Έμ‘° νμ΄μ§ λ₯Ό μ°Έμ‘°νμΈμ.
κΈ°ν
μ½λ νλ‘νμΌλ§
λ€μμ μ¬μ©νμ¬ μ€ν/μ²λ¦¬ν μ½λμ κΈ°κ°μ νμΈν©λλ€. with
λλ λ°μ½λ μ΄ν°λ‘ μ¬μ©ν μ μμ΅λλ€.
from ultralytics.utils.ops import Profile
with Profile(device=device) as dt:
pass # operation to measure
print(dt)
>>> "Elapsed time is 9.5367431640625e-07 s"
Ultralytics μ§μλλ νμ
Ultralytics μμ μ§μνλ μ΄λ―Έμ§ λλ λμμ νμμ νμμ νλ‘κ·Έλλ° λ°©μμΌλ‘ μ¬μ©νκ³ μΆκ±°λ μ¬μ©ν΄μΌ νλμ? νμν κ²½μ° μ΄ μμλ₯Ό μ¬μ©νμΈμ.
from ultralytics.data.utils import IMG_FORMATS
from ultralytics.data.utils import VID_FORMATS
print(IMG_FORMATS)
>>> ('bmp', 'dng', 'jpeg', 'jpg', 'mpo', 'png', 'tif', 'tiff', 'webp', 'pfm')
λΆν κ°λ₯ λ§λ€κΈ°
λ€μμ κ°μ₯ κ°κΉμ΄ μ μλ₯Ό κ³μ°ν©λλ€. x
λ‘ λλ λ κ· λ±νκ² λλ μ μλλ‘ ν©λλ€. y
.
from ultralytics.utils.ops import make_divisible
make_divisible(7, 3)
>>> 9
make_divisible(7, 2)
>>> 8
μμ± 2024-02-20, μ λ°μ΄νΈ 2024-05-08
μμ±μ: 리μ¦μ 무λμλ₯΄ (1), κΈλ μ‘°μ² (3), λ²ν ν (2)