ΠΡΠΎΡΡΡΠ΅ ΡΡΠΈΠ»ΠΈΡΡ
The ultralytics
ΠΠ°ΠΊΠ΅Ρ ΠΏΠΎΡΡΠ°Π²Π»ΡΠ΅ΡΡΡ Ρ ΠΎΠ³ΡΠΎΠΌΠ½ΡΠΌ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎΠΌ ΡΡΠΈΠ»ΠΈΡ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΌΠΎΠ³ΡΡ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠ°ΡΡ, ΡΠ»ΡΡΡΠΈΡΡ ΠΈ ΡΡΠΊΠΎΡΠΈΡΡ ΡΠ²ΠΎΠΈ ΡΠ°Π±ΠΎΡΠΈΠ΅ ΠΏΡΠΎΡΠ΅ΡΡΡ. ΠΡ
ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡΠΈ Π³ΠΎΡΠ°Π·Π΄ΠΎ Π±ΠΎΠ»ΡΡΠ΅, Π½ΠΎ Π²ΠΎΡ Π½Π΅ΠΊΠΎΡΠΎΡΡΠ΅, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΏΡΠΈΠ³ΠΎΠ΄ΡΡΡΡ Π±ΠΎΠ»ΡΡΠΈΠ½ΡΡΠ²Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ². ΠΠ½ΠΈ ΡΠ°ΠΊΠΆΠ΅ ΡΠ²Π»ΡΡΡΡΡ ΠΎΡΠ»ΠΈΡΠ½ΡΠΌ ΠΎΡΠΈΠ΅Π½ΡΠΈΡΠΎΠΌ ΠΏΡΠΈ ΠΎΠ±ΡΡΠ΅Π½ΠΈΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΡ.
Π‘ΠΌΠΎΡΡΠΈ: Ultralytics Π£ΡΠΈΠ»ΠΈΡΡ | ΠΠ²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠ°Ρ Π°Π½Π½ΠΎΡΠ°ΡΠΈΡ, API ΠΏΡΠΎΠ²ΠΎΠ΄Π½ΠΈΠΊΠ° ΠΈ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π°Π±ΠΎΡΠΎΠ² Π΄Π°Π½Π½ΡΡ
ΠΠ°Π½Π½ΡΠ΅
YOLO ΠΡΠΎΠ²ΠΎΠ΄Π½ΠΈΠΊ Π΄Π°Π½Π½ΡΡ
YOLO ΠΡΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»Ρ Π±ΡΠ» Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ Π² 8.1.0
ΡΠ±ΠΈΠ»Π΅ΠΉΠ½ΠΎΠ³ΠΎ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ ΠΈ ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΌΠΎΡΠ½ΡΠΌ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΎΠΌ, ΠΊΠΎΡΠΎΡΡΠΉ ΡΡ ΠΌΠΎΠΆΠ΅ΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ, ΡΡΠΎΠ±Ρ Π»ΡΡΡΠ΅ ΠΏΠΎΠ½ΡΡΡ ΡΠ²ΠΎΠΉ Π½Π°Π±ΠΎΡ Π΄Π°Π½Π½ΡΡ
. ΠΠ΄Π½Π° ΠΈΠ· ΠΊΠ»ΡΡΠ΅Π²ΡΡ
ΡΡΠ½ΠΊΡΠΈΠΉ, ΠΊΠΎΡΠΎΡΡΡ ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ 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 . ΠΠ»Ρ Π½Π°Π±ΠΎΡΠΎΠ² Π΄Π°Π½Π½ΡΡ
ΠΏΠΎ ΠΎΠ±Π½Π°ΡΡΠΆΠ΅Π½ΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² (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,
)
- ΠΠ· ΡΡΠΎΠΉ ΡΡΠ½ΠΊΡΠΈΠΈ Π½ΠΈΡΠ΅Π³ΠΎ Π½Π΅ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΡΡΡ
ΠΠ»Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΠΎΠΉ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΈ ΠΎ 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
)
ΠΠ³ΡΠ°Π½ΠΈΡΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ ΡΠ°ΠΌΠΊΠΈ
ΠΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΡ Bounding Box (Π³ΠΎΡΠΈΠ·ΠΎΠ½ΡΠ°Π»ΡΠ½ΡΠ΅)
Π§ΡΠΎΠ±Ρ ΡΠΏΡΠ°Π²Π»ΡΡΡ Π΄Π°Π½Π½ΡΠΌΠΈ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΡΠ΅Π»ΡΠ½ΡΡ
ΡΠ°ΠΌΠΎΠΊ, Π½ΡΠΆΠ½ΠΎ 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, 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)
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
Π‘ΠΌΠΎΡΡΠΈ docstring Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΡΡΠ½ΠΊΡΠΈΠΈ ΠΈΠ»ΠΈ ΠΏΠΎΡΠ΅ΡΠΈ 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
ΠΠ²ΡΠΎΡΡ: RizwanMunawar (1), glenn-jocher (3), Burhan-Q (2)