ultralytics 8.1.1__py3-none-any.whl → 8.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ultralytics might be problematic. Click here for more details.
- ultralytics/__init__.py +1 -1
- ultralytics/cfg/__init__.py +1 -1
- ultralytics/cfg/datasets/Argoverse.yaml +5 -7
- ultralytics/cfg/datasets/DOTAv1.5.yaml +4 -4
- ultralytics/cfg/datasets/DOTAv1.yaml +4 -4
- ultralytics/cfg/datasets/GlobalWheat2020.yaml +2 -4
- ultralytics/cfg/datasets/ImageNet.yaml +4 -6
- ultralytics/cfg/datasets/Objects365.yaml +3 -5
- ultralytics/cfg/datasets/SKU-110K.yaml +4 -6
- ultralytics/cfg/datasets/VOC.yaml +0 -2
- ultralytics/cfg/datasets/VisDrone.yaml +4 -6
- ultralytics/cfg/datasets/coco-pose.yaml +6 -7
- ultralytics/cfg/datasets/coco.yaml +5 -7
- ultralytics/cfg/datasets/coco128-seg.yaml +4 -6
- ultralytics/cfg/datasets/coco128.yaml +4 -6
- ultralytics/cfg/datasets/coco8-pose.yaml +5 -6
- ultralytics/cfg/datasets/coco8-seg.yaml +4 -6
- ultralytics/cfg/datasets/coco8.yaml +4 -6
- ultralytics/cfg/datasets/dota8.yaml +3 -3
- ultralytics/cfg/datasets/open-images-v7.yaml +4 -6
- ultralytics/cfg/datasets/tiger-pose.yaml +4 -5
- ultralytics/cfg/datasets/xView.yaml +3 -5
- ultralytics/cfg/default.yaml +103 -103
- ultralytics/cfg/models/rt-detr/rtdetr-l.yaml +27 -27
- ultralytics/cfg/models/rt-detr/rtdetr-resnet101.yaml +23 -23
- ultralytics/cfg/models/rt-detr/rtdetr-resnet50.yaml +23 -23
- ultralytics/cfg/models/rt-detr/rtdetr-x.yaml +27 -27
- ultralytics/cfg/models/v3/yolov3-spp.yaml +32 -34
- ultralytics/cfg/models/v3/yolov3-tiny.yaml +24 -26
- ultralytics/cfg/models/v3/yolov3.yaml +32 -34
- ultralytics/cfg/models/v5/yolov5-p6.yaml +41 -43
- ultralytics/cfg/models/v5/yolov5.yaml +26 -28
- ultralytics/cfg/models/v6/yolov6.yaml +17 -17
- ultralytics/cfg/models/v8/yolov8-cls-resnet101.yaml +25 -0
- ultralytics/cfg/models/v8/yolov8-cls-resnet50.yaml +25 -0
- ultralytics/cfg/models/v8/yolov8-cls.yaml +7 -7
- ultralytics/cfg/models/v8/yolov8-ghost-p2.yaml +26 -26
- ultralytics/cfg/models/v8/yolov8-ghost-p6.yaml +27 -27
- ultralytics/cfg/models/v8/yolov8-ghost.yaml +23 -23
- ultralytics/cfg/models/v8/yolov8-obb.yaml +23 -23
- ultralytics/cfg/models/v8/yolov8-p2.yaml +23 -23
- ultralytics/cfg/models/v8/yolov8-p6.yaml +24 -24
- ultralytics/cfg/models/v8/yolov8-pose-p6.yaml +25 -25
- ultralytics/cfg/models/v8/yolov8-pose.yaml +19 -19
- ultralytics/cfg/models/v8/yolov8-rtdetr.yaml +23 -23
- ultralytics/cfg/models/v8/yolov8-seg-p6.yaml +24 -24
- ultralytics/cfg/models/v8/yolov8-seg.yaml +18 -18
- ultralytics/cfg/models/v8/yolov8.yaml +23 -23
- ultralytics/cfg/trackers/botsort.yaml +7 -7
- ultralytics/cfg/trackers/bytetrack.yaml +6 -6
- ultralytics/data/annotator.py +1 -1
- ultralytics/data/augment.py +1 -2
- ultralytics/data/base.py +0 -1
- ultralytics/data/build.py +1 -2
- ultralytics/data/dataset.py +0 -1
- ultralytics/data/explorer/explorer.py +11 -12
- ultralytics/data/explorer/utils.py +3 -3
- ultralytics/data/split_dota.py +15 -23
- ultralytics/engine/model.py +12 -11
- ultralytics/engine/predictor.py +1 -1
- ultralytics/engine/trainer.py +1 -4
- ultralytics/hub/__init__.py +5 -3
- ultralytics/hub/auth.py +1 -2
- ultralytics/hub/session.py +14 -6
- ultralytics/hub/utils.py +4 -0
- ultralytics/models/fastsam/model.py +0 -1
- ultralytics/models/nas/model.py +0 -1
- ultralytics/models/rtdetr/train.py +0 -1
- ultralytics/models/rtdetr/val.py +1 -2
- ultralytics/models/sam/build.py +0 -1
- ultralytics/models/sam/model.py +0 -1
- ultralytics/models/sam/modules/encoders.py +1 -6
- ultralytics/models/sam/predict.py +0 -1
- ultralytics/models/utils/loss.py +0 -1
- ultralytics/models/yolo/detect/val.py +1 -2
- ultralytics/models/yolo/obb/val.py +14 -39
- ultralytics/nn/modules/head.py +5 -6
- ultralytics/nn/modules/utils.py +1 -1
- ultralytics/nn/tasks.py +1 -1
- ultralytics/solutions/ai_gym.py +9 -1
- ultralytics/solutions/distance_calculation.py +4 -8
- ultralytics/solutions/heatmap.py +16 -21
- ultralytics/solutions/object_counter.py +30 -29
- ultralytics/solutions/speed_estimation.py +19 -24
- ultralytics/trackers/track.py +0 -1
- ultralytics/trackers/utils/gmc.py +1 -1
- ultralytics/trackers/utils/matching.py +1 -3
- ultralytics/utils/benchmarks.py +2 -7
- ultralytics/utils/callbacks/base.py +1 -0
- ultralytics/utils/callbacks/comet.py +4 -22
- ultralytics/utils/callbacks/hub.py +1 -3
- ultralytics/utils/callbacks/neptune.py +1 -3
- ultralytics/utils/callbacks/tensorboard.py +2 -1
- ultralytics/utils/checks.py +2 -2
- ultralytics/utils/loss.py +3 -6
- ultralytics/utils/ops.py +8 -9
- ultralytics/utils/plotting.py +13 -15
- ultralytics/utils/tal.py +1 -2
- {ultralytics-8.1.1.dist-info → ultralytics-8.1.3.dist-info}/METADATA +15 -15
- ultralytics-8.1.3.dist-info/RECORD +190 -0
- ultralytics-8.1.1.dist-info/RECORD +0 -188
- {ultralytics-8.1.1.dist-info → ultralytics-8.1.3.dist-info}/LICENSE +0 -0
- {ultralytics-8.1.1.dist-info → ultralytics-8.1.3.dist-info}/WHEEL +0 -0
- {ultralytics-8.1.1.dist-info → ultralytics-8.1.3.dist-info}/entry_points.txt +0 -0
- {ultralytics-8.1.1.dist-info → ultralytics-8.1.3.dist-info}/top_level.txt +0 -0
|
@@ -2,45 +2,45 @@
|
|
|
2
2
|
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
|
|
3
3
|
|
|
4
4
|
# Parameters
|
|
5
|
-
nc: 80
|
|
5
|
+
nc: 80 # number of classes
|
|
6
6
|
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
|
|
7
7
|
# [depth, width, max_channels]
|
|
8
|
-
n: [0.33, 0.25, 1024]
|
|
9
|
-
s: [0.33, 0.50, 1024]
|
|
10
|
-
m: [0.67, 0.75, 768]
|
|
11
|
-
l: [1.00, 1.00, 512]
|
|
12
|
-
x: [1.00, 1.25, 512]
|
|
8
|
+
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
|
|
9
|
+
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
|
|
10
|
+
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
|
|
11
|
+
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
|
|
12
|
+
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
|
|
13
13
|
|
|
14
14
|
# YOLOv8.0n backbone
|
|
15
15
|
backbone:
|
|
16
16
|
# [from, repeats, module, args]
|
|
17
|
-
- [-1, 1, Conv, [64, 3, 2]]
|
|
18
|
-
- [-1, 1, Conv, [128, 3, 2]]
|
|
17
|
+
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
|
|
18
|
+
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
|
|
19
19
|
- [-1, 3, C2f, [128, True]]
|
|
20
|
-
- [-1, 1, Conv, [256, 3, 2]]
|
|
20
|
+
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
|
|
21
21
|
- [-1, 6, C2f, [256, True]]
|
|
22
|
-
- [-1, 1, Conv, [512, 3, 2]]
|
|
22
|
+
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
|
|
23
23
|
- [-1, 6, C2f, [512, True]]
|
|
24
|
-
- [-1, 1, Conv, [1024, 3, 2]]
|
|
24
|
+
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
|
|
25
25
|
- [-1, 3, C2f, [1024, True]]
|
|
26
|
-
- [-1, 1, SPPF, [1024, 5]]
|
|
26
|
+
- [-1, 1, SPPF, [1024, 5]] # 9
|
|
27
27
|
|
|
28
28
|
# YOLOv8.0n head
|
|
29
29
|
head:
|
|
30
|
-
- [-1, 1, nn.Upsample, [None, 2,
|
|
31
|
-
- [[-1, 6], 1, Concat, [1]]
|
|
32
|
-
- [-1, 3, C2f, [512]]
|
|
30
|
+
- [-1, 1, nn.Upsample, [None, 2, "nearest"]]
|
|
31
|
+
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
|
|
32
|
+
- [-1, 3, C2f, [512]] # 12
|
|
33
33
|
|
|
34
|
-
- [-1, 1, nn.Upsample, [None, 2,
|
|
35
|
-
- [[-1, 4], 1, Concat, [1]]
|
|
36
|
-
- [-1, 3, C2f, [256]]
|
|
34
|
+
- [-1, 1, nn.Upsample, [None, 2, "nearest"]]
|
|
35
|
+
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
|
|
36
|
+
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
|
|
37
37
|
|
|
38
38
|
- [-1, 1, Conv, [256, 3, 2]]
|
|
39
|
-
- [[-1, 12], 1, Concat, [1]]
|
|
40
|
-
- [-1, 3, C2f, [512]]
|
|
39
|
+
- [[-1, 12], 1, Concat, [1]] # cat head P4
|
|
40
|
+
- [-1, 3, C2f, [512]] # 18 (P4/16-medium)
|
|
41
41
|
|
|
42
42
|
- [-1, 1, Conv, [512, 3, 2]]
|
|
43
|
-
- [[-1, 9], 1, Concat, [1]]
|
|
44
|
-
- [-1, 3, C2f, [1024]]
|
|
43
|
+
- [[-1, 9], 1, Concat, [1]] # cat head P5
|
|
44
|
+
- [-1, 3, C2f, [1024]] # 21 (P5/32-large)
|
|
45
45
|
|
|
46
|
-
- [[15, 18, 21], 1, Detect, [nc]]
|
|
46
|
+
- [[15, 18, 21], 1, Detect, [nc]] # Detect(P3, P4, P5)
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
|
2
2
|
# Default YOLO tracker settings for BoT-SORT tracker https://github.com/NirAharon/BoT-SORT
|
|
3
3
|
|
|
4
|
-
tracker_type: botsort
|
|
5
|
-
track_high_thresh: 0.5
|
|
6
|
-
track_low_thresh: 0.1
|
|
7
|
-
new_track_thresh: 0.6
|
|
8
|
-
track_buffer: 30
|
|
9
|
-
match_thresh: 0.8
|
|
4
|
+
tracker_type: botsort # tracker type, ['botsort', 'bytetrack']
|
|
5
|
+
track_high_thresh: 0.5 # threshold for the first association
|
|
6
|
+
track_low_thresh: 0.1 # threshold for the second association
|
|
7
|
+
new_track_thresh: 0.6 # threshold for init new track if the detection does not match any tracks
|
|
8
|
+
track_buffer: 30 # buffer to calculate the time when to remove tracks
|
|
9
|
+
match_thresh: 0.8 # threshold for matching tracks
|
|
10
10
|
# min_box_area: 10 # threshold for min box areas(for tracker evaluation, not used for now)
|
|
11
11
|
# mot20: False # for tracker evaluation(not used for now)
|
|
12
12
|
|
|
13
13
|
# BoT-SORT settings
|
|
14
|
-
gmc_method: sparseOptFlow
|
|
14
|
+
gmc_method: sparseOptFlow # method of global motion compensation
|
|
15
15
|
# ReID model related thresh (not supported yet)
|
|
16
16
|
proximity_thresh: 0.5
|
|
17
17
|
appearance_thresh: 0.25
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
|
2
2
|
# Default YOLO tracker settings for ByteTrack tracker https://github.com/ifzhang/ByteTrack
|
|
3
3
|
|
|
4
|
-
tracker_type: bytetrack
|
|
5
|
-
track_high_thresh: 0.5
|
|
6
|
-
track_low_thresh: 0.1
|
|
7
|
-
new_track_thresh: 0.6
|
|
8
|
-
track_buffer: 30
|
|
9
|
-
match_thresh: 0.8
|
|
4
|
+
tracker_type: bytetrack # tracker type, ['botsort', 'bytetrack']
|
|
5
|
+
track_high_thresh: 0.5 # threshold for the first association
|
|
6
|
+
track_low_thresh: 0.1 # threshold for the second association
|
|
7
|
+
new_track_thresh: 0.6 # threshold for init new track if the detection does not match any tracks
|
|
8
|
+
track_buffer: 30 # buffer to calculate the time when to remove tracks
|
|
9
|
+
match_thresh: 0.8 # threshold for matching tracks
|
|
10
10
|
# min_box_area: 10 # threshold for min box areas(for tracker evaluation, not used for now)
|
|
11
11
|
# mot20: False # for tracker evaluation(not used for now)
|
ultralytics/data/annotator.py
CHANGED
|
@@ -41,7 +41,7 @@ def auto_annotate(data, det_model="yolov8x.pt", sam_model="sam_b.pt", device="",
|
|
|
41
41
|
sam_results = sam_model(result.orig_img, bboxes=boxes, verbose=False, save=False, device=device)
|
|
42
42
|
segments = sam_results[0].masks.xyn # noqa
|
|
43
43
|
|
|
44
|
-
with open(f"{
|
|
44
|
+
with open(f"{Path(output_dir) / Path(result.path).stem}.txt", "w") as f:
|
|
45
45
|
for i in range(len(segments)):
|
|
46
46
|
s = segments[i]
|
|
47
47
|
if len(s) == 0:
|
ultralytics/data/augment.py
CHANGED
|
@@ -15,7 +15,6 @@ from ultralytics.utils.instance import Instances
|
|
|
15
15
|
from ultralytics.utils.metrics import bbox_ioa
|
|
16
16
|
from ultralytics.utils.ops import segment2box, xyxyxyxy2xywhr
|
|
17
17
|
from ultralytics.utils.torch_utils import TORCHVISION_0_10, TORCHVISION_0_11, TORCHVISION_0_13
|
|
18
|
-
|
|
19
18
|
from .utils import polygons2masks, polygons2masks_overlap
|
|
20
19
|
|
|
21
20
|
DEFAULT_MEAN = (0.0, 0.0, 0.0)
|
|
@@ -1028,7 +1027,7 @@ def classify_transforms(
|
|
|
1028
1027
|
|
|
1029
1028
|
if isinstance(size, (tuple, list)):
|
|
1030
1029
|
assert len(size) == 2
|
|
1031
|
-
scale_size = tuple(
|
|
1030
|
+
scale_size = tuple(math.floor(x / crop_fraction) for x in size)
|
|
1032
1031
|
else:
|
|
1033
1032
|
scale_size = math.floor(size / crop_fraction)
|
|
1034
1033
|
scale_size = (scale_size, scale_size)
|
ultralytics/data/base.py
CHANGED
ultralytics/data/build.py
CHANGED
|
@@ -22,7 +22,6 @@ from ultralytics.data.loaders import (
|
|
|
22
22
|
from ultralytics.data.utils import IMG_FORMATS, VID_FORMATS
|
|
23
23
|
from ultralytics.utils import RANK, colorstr
|
|
24
24
|
from ultralytics.utils.checks import check_file
|
|
25
|
-
|
|
26
25
|
from .dataset import YOLODataset
|
|
27
26
|
from .utils import PIN_MEMORY
|
|
28
27
|
|
|
@@ -108,7 +107,7 @@ def build_dataloader(dataset, batch, workers, shuffle=True, rank=-1):
|
|
|
108
107
|
"""Return an InfiniteDataLoader or DataLoader for training or validation set."""
|
|
109
108
|
batch = min(batch, len(dataset))
|
|
110
109
|
nd = torch.cuda.device_count() # number of CUDA devices
|
|
111
|
-
nw = min([os.cpu_count() // max(nd, 1),
|
|
110
|
+
nw = min([os.cpu_count() // max(nd, 1), workers]) # number of workers
|
|
112
111
|
sampler = None if rank == -1 else distributed.DistributedSampler(dataset, shuffle=shuffle)
|
|
113
112
|
generator = torch.Generator()
|
|
114
113
|
generator.manual_seed(6148914691236517205 + RANK)
|
ultralytics/data/dataset.py
CHANGED
|
@@ -12,7 +12,6 @@ from PIL import Image
|
|
|
12
12
|
|
|
13
13
|
from ultralytics.utils import LOCAL_RANK, NUM_THREADS, TQDM, colorstr, is_dir_writeable
|
|
14
14
|
from ultralytics.utils.ops import resample_segments
|
|
15
|
-
|
|
16
15
|
from .augment import Compose, Format, Instances, LetterBox, classify_augmentations, classify_transforms, v8_transforms
|
|
17
16
|
from .base import BaseDataset
|
|
18
17
|
from .utils import HELP_URL, LOGGER, get_hash, img2label_paths, verify_image, verify_image_label
|
|
@@ -7,9 +7,9 @@ from typing import Any, List, Tuple, Union
|
|
|
7
7
|
import cv2
|
|
8
8
|
import numpy as np
|
|
9
9
|
import torch
|
|
10
|
+
from PIL import Image
|
|
10
11
|
from matplotlib import pyplot as plt
|
|
11
12
|
from pandas import DataFrame
|
|
12
|
-
from PIL import Image
|
|
13
13
|
from tqdm import tqdm
|
|
14
14
|
|
|
15
15
|
from ultralytics.data.augment import Format
|
|
@@ -17,7 +17,6 @@ from ultralytics.data.dataset import YOLODataset
|
|
|
17
17
|
from ultralytics.data.utils import check_det_dataset
|
|
18
18
|
from ultralytics.models.yolo.model import YOLO
|
|
19
19
|
from ultralytics.utils import LOGGER, IterableSimpleNamespace, checks
|
|
20
|
-
|
|
21
20
|
from .utils import get_sim_index_schema, get_table_schema, plot_query_result, prompt_sql_query, sanitize_batch
|
|
22
21
|
|
|
23
22
|
|
|
@@ -188,10 +187,10 @@ class Explorer:
|
|
|
188
187
|
result = exp.sql_query(query)
|
|
189
188
|
```
|
|
190
189
|
"""
|
|
191
|
-
assert return_type in
|
|
190
|
+
assert return_type in {
|
|
192
191
|
"pandas",
|
|
193
192
|
"arrow",
|
|
194
|
-
|
|
193
|
+
}, f"Return type should be either `pandas` or `arrow`, but got {return_type}"
|
|
195
194
|
import duckdb
|
|
196
195
|
|
|
197
196
|
if self.table is None:
|
|
@@ -208,10 +207,10 @@ class Explorer:
|
|
|
208
207
|
LOGGER.info(f"Running query: {query}")
|
|
209
208
|
|
|
210
209
|
rs = duckdb.sql(query)
|
|
211
|
-
if return_type == "
|
|
212
|
-
return rs.df()
|
|
213
|
-
elif return_type == "arrow":
|
|
210
|
+
if return_type == "arrow":
|
|
214
211
|
return rs.arrow()
|
|
212
|
+
elif return_type == "pandas":
|
|
213
|
+
return rs.df()
|
|
215
214
|
|
|
216
215
|
def plot_sql_query(self, query: str, labels: bool = True) -> Image.Image:
|
|
217
216
|
"""
|
|
@@ -264,17 +263,17 @@ class Explorer:
|
|
|
264
263
|
similar = exp.get_similar(img='https://ultralytics.com/images/zidane.jpg')
|
|
265
264
|
```
|
|
266
265
|
"""
|
|
267
|
-
assert return_type in
|
|
266
|
+
assert return_type in {
|
|
268
267
|
"pandas",
|
|
269
268
|
"arrow",
|
|
270
|
-
|
|
269
|
+
}, f"Return type should be either `pandas` or `arrow`, but got {return_type}"
|
|
271
270
|
img = self._check_imgs_or_idxs(img, idx)
|
|
272
271
|
similar = self.query(img, limit=limit)
|
|
273
272
|
|
|
274
|
-
if return_type == "
|
|
275
|
-
return similar.to_pandas()
|
|
276
|
-
elif return_type == "arrow":
|
|
273
|
+
if return_type == "arrow":
|
|
277
274
|
return similar
|
|
275
|
+
elif return_type == "pandas":
|
|
276
|
+
return similar.to_pandas()
|
|
278
277
|
|
|
279
278
|
def plot_similar(
|
|
280
279
|
self,
|
|
@@ -98,9 +98,9 @@ def plot_query_result(similar_set, plot_labels=True):
|
|
|
98
98
|
plot_kpts.append(kpt)
|
|
99
99
|
batch_idx.append(np.ones(len(np.array(bboxes[i], dtype=np.float32))) * i)
|
|
100
100
|
imgs = np.stack(imgs, axis=0)
|
|
101
|
-
masks = np.stack(plot_masks, axis=0) if
|
|
102
|
-
kpts = np.concatenate(plot_kpts, axis=0) if
|
|
103
|
-
boxes = xyxy2xywh(np.concatenate(plot_boxes, axis=0)) if
|
|
101
|
+
masks = np.stack(plot_masks, axis=0) if plot_masks else np.zeros(0, dtype=np.uint8)
|
|
102
|
+
kpts = np.concatenate(plot_kpts, axis=0) if plot_kpts else np.zeros((0, 51), dtype=np.float32)
|
|
103
|
+
boxes = xyxy2xywh(np.concatenate(plot_boxes, axis=0)) if plot_boxes else np.zeros(0, dtype=np.float32)
|
|
104
104
|
batch_idx = np.concatenate(batch_idx, axis=0)
|
|
105
105
|
cls = np.concatenate([np.array(c, dtype=np.int32) for c in cls], axis=0)
|
|
106
106
|
|
ultralytics/data/split_dota.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
|
2
2
|
|
|
3
3
|
import itertools
|
|
4
|
-
import os
|
|
5
4
|
from glob import glob
|
|
6
5
|
from math import ceil
|
|
7
6
|
from pathlib import Path
|
|
@@ -73,9 +72,9 @@ def load_yolo_dota(data_root, split="train"):
|
|
|
73
72
|
- val
|
|
74
73
|
"""
|
|
75
74
|
assert split in ["train", "val"]
|
|
76
|
-
im_dir =
|
|
77
|
-
assert
|
|
78
|
-
im_files = glob(
|
|
75
|
+
im_dir = Path(data_root) / "images" / split
|
|
76
|
+
assert im_dir.exists(), f"Can't find {im_dir}, please check your data root."
|
|
77
|
+
im_files = glob(str(Path(data_root) / "images" / split / "*"))
|
|
79
78
|
lb_files = img2label_paths(im_files)
|
|
80
79
|
annos = []
|
|
81
80
|
for im_file, lb_file in zip(im_files, lb_files):
|
|
@@ -94,7 +93,7 @@ def get_windows(im_size, crop_sizes=[1024], gaps=[200], im_rate_thr=0.6, eps=0.0
|
|
|
94
93
|
Args:
|
|
95
94
|
im_size (tuple): Original image size, (h, w).
|
|
96
95
|
crop_sizes (List(int)): Crop size of windows.
|
|
97
|
-
gaps (List(int)): Gap between
|
|
96
|
+
gaps (List(int)): Gap between crops.
|
|
98
97
|
im_rate_thr (float): Threshold of windows areas divided by image ares.
|
|
99
98
|
"""
|
|
100
99
|
h, w = im_size
|
|
@@ -139,10 +138,9 @@ def get_window_obj(anno, windows, iof_thr=0.7):
|
|
|
139
138
|
label[:, 2::2] *= h
|
|
140
139
|
iofs = bbox_iof(label[:, 1:], windows)
|
|
141
140
|
# Unnormalized and misaligned coordinates
|
|
142
|
-
|
|
141
|
+
return [(label[iofs[:, i] >= iof_thr]) for i in range(len(windows))] # window_anns
|
|
143
142
|
else:
|
|
144
|
-
|
|
145
|
-
return window_anns
|
|
143
|
+
return [np.zeros((0, 9), dtype=np.float32) for _ in range(len(windows))] # window_anns
|
|
146
144
|
|
|
147
145
|
|
|
148
146
|
def crop_and_save(anno, windows, window_objs, im_dir, lb_dir):
|
|
@@ -170,11 +168,11 @@ def crop_and_save(anno, windows, window_objs, im_dir, lb_dir):
|
|
|
170
168
|
name = Path(anno["filepath"]).stem
|
|
171
169
|
for i, window in enumerate(windows):
|
|
172
170
|
x_start, y_start, x_stop, y_stop = window.tolist()
|
|
173
|
-
new_name = name
|
|
171
|
+
new_name = f"{name}__{x_stop - x_start}__{x_start}___{y_start}"
|
|
174
172
|
patch_im = im[y_start:y_stop, x_start:x_stop]
|
|
175
173
|
ph, pw = patch_im.shape[:2]
|
|
176
174
|
|
|
177
|
-
cv2.imwrite(
|
|
175
|
+
cv2.imwrite(str(Path(im_dir) / f"{new_name}.jpg"), patch_im)
|
|
178
176
|
label = window_objs[i]
|
|
179
177
|
if len(label) == 0:
|
|
180
178
|
continue
|
|
@@ -183,7 +181,7 @@ def crop_and_save(anno, windows, window_objs, im_dir, lb_dir):
|
|
|
183
181
|
label[:, 1::2] /= pw
|
|
184
182
|
label[:, 2::2] /= ph
|
|
185
183
|
|
|
186
|
-
with open(
|
|
184
|
+
with open(Path(lb_dir) / f"{new_name}.txt", "w") as f:
|
|
187
185
|
for lb in label:
|
|
188
186
|
formatted_coords = ["{:.6g}".format(coord) for coord in lb[1:]]
|
|
189
187
|
f.write(f"{int(lb[0])} {' '.join(formatted_coords)}\n")
|
|
@@ -270,8 +268,8 @@ def split_test(data_root, save_dir, crop_size=1024, gap=200, rates=[1.0]):
|
|
|
270
268
|
save_dir = Path(save_dir) / "images" / "test"
|
|
271
269
|
save_dir.mkdir(parents=True, exist_ok=True)
|
|
272
270
|
|
|
273
|
-
im_dir = Path(
|
|
274
|
-
assert im_dir.exists(), f"Can't find {
|
|
271
|
+
im_dir = Path(data_root) / "images" / "test"
|
|
272
|
+
assert im_dir.exists(), f"Can't find {im_dir}, please check your data root."
|
|
275
273
|
im_files = glob(str(im_dir / "*"))
|
|
276
274
|
for im_file in tqdm(im_files, total=len(im_files), desc="test"):
|
|
277
275
|
w, h = exif_size(Image.open(im_file))
|
|
@@ -280,17 +278,11 @@ def split_test(data_root, save_dir, crop_size=1024, gap=200, rates=[1.0]):
|
|
|
280
278
|
name = Path(im_file).stem
|
|
281
279
|
for window in windows:
|
|
282
280
|
x_start, y_start, x_stop, y_stop = window.tolist()
|
|
283
|
-
new_name = name
|
|
281
|
+
new_name = f"{name}__{x_stop - x_start}__{x_start}___{y_start}"
|
|
284
282
|
patch_im = im[y_start:y_stop, x_start:x_stop]
|
|
285
|
-
cv2.imwrite(
|
|
283
|
+
cv2.imwrite(str(save_dir / f"{new_name}.jpg"), patch_im)
|
|
286
284
|
|
|
287
285
|
|
|
288
286
|
if __name__ == "__main__":
|
|
289
|
-
split_trainval(
|
|
290
|
-
|
|
291
|
-
save_dir="DOTAv2-split",
|
|
292
|
-
)
|
|
293
|
-
split_test(
|
|
294
|
-
data_root="DOTAv2",
|
|
295
|
-
save_dir="DOTAv2-split",
|
|
296
|
-
)
|
|
287
|
+
split_trainval(data_root="DOTAv2", save_dir="DOTAv2-split")
|
|
288
|
+
split_test(data_root="DOTAv2", save_dir="DOTAv2-split")
|
ultralytics/engine/model.py
CHANGED
|
@@ -5,11 +5,10 @@ import sys
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Union
|
|
7
7
|
|
|
8
|
-
from hub_sdk.config import HUB_WEB_ROOT
|
|
9
|
-
|
|
10
8
|
from ultralytics.cfg import TASK2DATA, get_cfg, get_save_dir
|
|
11
9
|
from ultralytics.nn.tasks import attempt_load_one_weight, guess_model_task, nn, yaml_model_load
|
|
12
10
|
from ultralytics.utils import ASSETS, DEFAULT_CFG_DICT, LOGGER, RANK, SETTINGS, callbacks, checks, emojis, yaml_load
|
|
11
|
+
from ultralytics.hub.utils import HUB_WEB_ROOT
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
class Model(nn.Module):
|
|
@@ -53,13 +52,14 @@ class Model(nn.Module):
|
|
|
53
52
|
list(ultralytics.engine.results.Results): The prediction results.
|
|
54
53
|
"""
|
|
55
54
|
|
|
56
|
-
def __init__(self, model: Union[str, Path] = "yolov8n.pt", task=None) -> None:
|
|
55
|
+
def __init__(self, model: Union[str, Path] = "yolov8n.pt", task=None, verbose=False) -> None:
|
|
57
56
|
"""
|
|
58
57
|
Initializes the YOLO model.
|
|
59
58
|
|
|
60
59
|
Args:
|
|
61
60
|
model (Union[str, Path], optional): Path or name of the model to load or create. Defaults to 'yolov8n.pt'.
|
|
62
61
|
task (Any, optional): Task type for the YOLO model. Defaults to None.
|
|
62
|
+
verbose (bool, optional): Whether to enable verbose mode.
|
|
63
63
|
"""
|
|
64
64
|
super().__init__()
|
|
65
65
|
self.callbacks = callbacks.get_default_callbacks()
|
|
@@ -73,11 +73,12 @@ class Model(nn.Module):
|
|
|
73
73
|
self.metrics = None # validation/training metrics
|
|
74
74
|
self.session = None # HUB session
|
|
75
75
|
self.task = task # task type
|
|
76
|
-
model = str(model).strip() # strip spaces
|
|
76
|
+
self.model_name = model = str(model).strip() # strip spaces
|
|
77
77
|
|
|
78
78
|
# Check if Ultralytics HUB model from https://hub.ultralytics.com
|
|
79
79
|
if self.is_hub_model(model):
|
|
80
80
|
# Fetch model from HUB
|
|
81
|
+
checks.check_requirements("hub-sdk>0.0.2")
|
|
81
82
|
self.session = self._get_hub_session(model)
|
|
82
83
|
model = self.session.model_file
|
|
83
84
|
|
|
@@ -90,9 +91,9 @@ class Model(nn.Module):
|
|
|
90
91
|
# Load or create new YOLO model
|
|
91
92
|
model = checks.check_model_file_from_stem(model) # add suffix, i.e. yolov8n -> yolov8n.pt
|
|
92
93
|
if Path(model).suffix in (".yaml", ".yml"):
|
|
93
|
-
self._new(model, task)
|
|
94
|
+
self._new(model, task=task, verbose=verbose)
|
|
94
95
|
else:
|
|
95
|
-
self._load(model, task)
|
|
96
|
+
self._load(model, task=task)
|
|
96
97
|
|
|
97
98
|
self.model_name = model
|
|
98
99
|
|
|
@@ -123,11 +124,11 @@ class Model(nn.Module):
|
|
|
123
124
|
(
|
|
124
125
|
model.startswith(f"{HUB_WEB_ROOT}/models/"), # i.e. https://hub.ultralytics.com/models/MODEL_ID
|
|
125
126
|
[len(x) for x in model.split("_")] == [42, 20], # APIKEY_MODELID
|
|
126
|
-
len(model) == 20 and not Path(model).exists() and all(x not in model for x in "./\\"),
|
|
127
|
+
len(model) == 20 and not Path(model).exists() and all(x not in model for x in "./\\"), # MODELID
|
|
127
128
|
)
|
|
128
|
-
)
|
|
129
|
+
)
|
|
129
130
|
|
|
130
|
-
def _new(self, cfg: str, task=None, model=None, verbose=
|
|
131
|
+
def _new(self, cfg: str, task=None, model=None, verbose=False):
|
|
131
132
|
"""
|
|
132
133
|
Initializes a new model and infers the task type from the model definitions.
|
|
133
134
|
|
|
@@ -382,8 +383,8 @@ class Model(nn.Module):
|
|
|
382
383
|
# Check model was created
|
|
383
384
|
if not getattr(self.session.model, "id", None):
|
|
384
385
|
self.session = None
|
|
385
|
-
except PermissionError:
|
|
386
|
-
# Ignore
|
|
386
|
+
except (PermissionError, ModuleNotFoundError):
|
|
387
|
+
# Ignore PermissionError and ModuleNotFoundError which indicates hub-sdk not installed
|
|
387
388
|
pass
|
|
388
389
|
|
|
389
390
|
self.trainer.hub_session = self.session # attach optional HUB session
|
ultralytics/engine/predictor.py
CHANGED
|
@@ -210,7 +210,7 @@ class BasePredictor:
|
|
|
210
210
|
It uses always generator as outputs as not required by CLI mode.
|
|
211
211
|
"""
|
|
212
212
|
gen = self.stream_inference(source, model)
|
|
213
|
-
for _ in gen: # running CLI inference without accumulating any outputs (do not modify)
|
|
213
|
+
for _ in gen: # noqa, running CLI inference without accumulating any outputs (do not modify)
|
|
214
214
|
pass
|
|
215
215
|
|
|
216
216
|
def setup_source(self, source):
|
ultralytics/engine/trainer.py
CHANGED
|
@@ -332,10 +332,7 @@ class BaseTrainer:
|
|
|
332
332
|
f'Image sizes {self.args.imgsz} train, {self.args.imgsz} val\n'
|
|
333
333
|
f'Using {self.train_loader.num_workers * (world_size or 1)} dataloader workers\n'
|
|
334
334
|
f"Logging results to {colorstr('bold', self.save_dir)}\n"
|
|
335
|
-
f'Starting training for '
|
|
336
|
-
f'{self.args.time} hours...'
|
|
337
|
-
if self.args.time
|
|
338
|
-
else f"{self.epochs} epochs..."
|
|
335
|
+
f'Starting training for ' + (f"{self.args.time} hours..." if self.args.time else f"{self.epochs} epochs...")
|
|
339
336
|
)
|
|
340
337
|
if self.args.close_mosaic:
|
|
341
338
|
base_idx = (self.epochs - self.args.close_mosaic) * nb
|
ultralytics/hub/__init__.py
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
|
2
2
|
|
|
3
3
|
import requests
|
|
4
|
-
from hub_sdk import HUB_API_ROOT, HUB_WEB_ROOT, HUBClient
|
|
5
4
|
|
|
6
5
|
from ultralytics.data.utils import HUBDatasetStats
|
|
7
6
|
from ultralytics.hub.auth import Auth
|
|
8
|
-
from ultralytics.hub.utils import PREFIX
|
|
9
|
-
from ultralytics.utils import LOGGER, SETTINGS
|
|
7
|
+
from ultralytics.hub.utils import HUB_API_ROOT, HUB_WEB_ROOT, PREFIX
|
|
8
|
+
from ultralytics.utils import LOGGER, SETTINGS, checks
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
def login(api_key: str = None, save=True) -> bool:
|
|
@@ -21,6 +20,9 @@ def login(api_key: str = None, save=True) -> bool:
|
|
|
21
20
|
Returns:
|
|
22
21
|
bool: True if authentication is successful, False otherwise.
|
|
23
22
|
"""
|
|
23
|
+
checks.check_requirements("hub-sdk>=0.0.2")
|
|
24
|
+
from hub_sdk import HUBClient
|
|
25
|
+
|
|
24
26
|
api_key_url = f"{HUB_WEB_ROOT}/settings?tab=api+keys" # set the redirect URL
|
|
25
27
|
saved_key = SETTINGS.get("api_key")
|
|
26
28
|
active_key = api_key or saved_key
|
ultralytics/hub/auth.py
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
|
2
2
|
|
|
3
3
|
import requests
|
|
4
|
-
from hub_sdk import HUB_API_ROOT, HUB_WEB_ROOT
|
|
5
4
|
|
|
6
|
-
from ultralytics.hub.utils import PREFIX, request_with_credentials
|
|
5
|
+
from ultralytics.hub.utils import HUB_API_ROOT, HUB_WEB_ROOT, PREFIX, request_with_credentials
|
|
7
6
|
from ultralytics.utils import LOGGER, SETTINGS, emojis, is_colab
|
|
8
7
|
|
|
9
8
|
API_KEY_URL = f"{HUB_WEB_ROOT}/settings?tab=api+keys"
|
ultralytics/hub/session.py
CHANGED
|
@@ -6,9 +6,8 @@ from http import HTTPStatus
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
8
|
import requests
|
|
9
|
-
from hub_sdk import HUB_WEB_ROOT, HUBClient
|
|
10
9
|
|
|
11
|
-
from ultralytics.hub.utils import HELP_MSG, PREFIX, TQDM
|
|
10
|
+
from ultralytics.hub.utils import HUB_WEB_ROOT, HELP_MSG, PREFIX, TQDM
|
|
12
11
|
from ultralytics.utils import LOGGER, SETTINGS, __version__, checks, emojis, is_colab
|
|
13
12
|
from ultralytics.utils.errors import HUBModelError
|
|
14
13
|
|
|
@@ -43,7 +42,10 @@ class HUBTrainingSession:
|
|
|
43
42
|
Raises:
|
|
44
43
|
ValueError: If the provided model identifier is invalid.
|
|
45
44
|
ConnectionError: If connecting with global API key is not supported.
|
|
45
|
+
ModuleNotFoundError: If hub-sdk package is not installed.
|
|
46
46
|
"""
|
|
47
|
+
from hub_sdk import HUBClient
|
|
48
|
+
|
|
47
49
|
self.rate_limits = {
|
|
48
50
|
"metrics": 3.0,
|
|
49
51
|
"ckpt": 900.0,
|
|
@@ -68,8 +70,11 @@ class HUBTrainingSession:
|
|
|
68
70
|
self.model = self.client.model() # load empty model
|
|
69
71
|
|
|
70
72
|
def load_model(self, model_id):
|
|
71
|
-
|
|
73
|
+
"""Loads an existing model from Ultralytics HUB using the provided model identifier."""
|
|
72
74
|
self.model = self.client.model(model_id)
|
|
75
|
+
if not self.model.data: # then model does not exist
|
|
76
|
+
raise ValueError(emojis("❌ The specified HUB model does not exist")) # TODO: improve error handling
|
|
77
|
+
|
|
73
78
|
self.model_url = f"{HUB_WEB_ROOT}/models/{self.model.id}"
|
|
74
79
|
|
|
75
80
|
self._set_train_args()
|
|
@@ -79,7 +84,7 @@ class HUBTrainingSession:
|
|
|
79
84
|
LOGGER.info(f"{PREFIX}View model at {self.model_url} 🚀")
|
|
80
85
|
|
|
81
86
|
def create_model(self, model_args):
|
|
82
|
-
|
|
87
|
+
"""Initializes a HUB training session with the specified model identifier."""
|
|
83
88
|
payload = {
|
|
84
89
|
"config": {
|
|
85
90
|
"batchSize": model_args.get("batch", -1),
|
|
@@ -165,6 +170,7 @@ class HUBTrainingSession:
|
|
|
165
170
|
return api_key, model_id, filename
|
|
166
171
|
|
|
167
172
|
def _set_train_args(self, **kwargs):
|
|
173
|
+
"""Initializes training arguments and creates a model entry on the Ultralytics HUB."""
|
|
168
174
|
if self.model.is_trained():
|
|
169
175
|
# Model is already trained
|
|
170
176
|
raise ValueError(emojis(f"Model is already trained and uploaded to {self.model_url} 🚀"))
|
|
@@ -176,6 +182,7 @@ class HUBTrainingSession:
|
|
|
176
182
|
else:
|
|
177
183
|
# Model has no saved weights
|
|
178
184
|
def get_train_args(config):
|
|
185
|
+
"""Parses an identifier to extract API key, model ID, and filename if applicable."""
|
|
179
186
|
return {
|
|
180
187
|
"batch": config["batchSize"],
|
|
181
188
|
"epochs": config["epochs"],
|
|
@@ -210,6 +217,7 @@ class HUBTrainingSession:
|
|
|
210
217
|
**kwargs,
|
|
211
218
|
):
|
|
212
219
|
def retry_request():
|
|
220
|
+
"""Attempts to call `request_func` with retries, timeout, and optional threading."""
|
|
213
221
|
t0 = time.time() # Record the start time for the timeout
|
|
214
222
|
for i in range(retry + 1):
|
|
215
223
|
if (time.time() - t0) > timeout:
|
|
@@ -251,13 +259,13 @@ class HUBTrainingSession:
|
|
|
251
259
|
return retry_request()
|
|
252
260
|
|
|
253
261
|
def _should_retry(self, status_code):
|
|
254
|
-
|
|
262
|
+
"""Determines if a request should be retried based on the HTTP status code."""
|
|
255
263
|
retry_codes = {
|
|
256
264
|
HTTPStatus.REQUEST_TIMEOUT,
|
|
257
265
|
HTTPStatus.BAD_GATEWAY,
|
|
258
266
|
HTTPStatus.GATEWAY_TIMEOUT,
|
|
259
267
|
}
|
|
260
|
-
return
|
|
268
|
+
return status_code in retry_codes
|
|
261
269
|
|
|
262
270
|
def _get_failure_message(self, response: requests.Response, retry: int, timeout: int):
|
|
263
271
|
"""
|
ultralytics/hub/utils.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
|
2
2
|
|
|
3
|
+
import os
|
|
3
4
|
import platform
|
|
4
5
|
import random
|
|
5
6
|
import sys
|
|
@@ -27,6 +28,9 @@ from ultralytics.utils import (
|
|
|
27
28
|
)
|
|
28
29
|
from ultralytics.utils.downloads import GITHUB_ASSETS_NAMES
|
|
29
30
|
|
|
31
|
+
HUB_API_ROOT = os.environ.get("ULTRALYTICS_HUB_API", "https://api.ultralytics.com")
|
|
32
|
+
HUB_WEB_ROOT = os.environ.get("ULTRALYTICS_HUB_WEB", "https://hub.ultralytics.com")
|
|
33
|
+
|
|
30
34
|
PREFIX = colorstr("Ultralytics HUB: ")
|
|
31
35
|
HELP_MSG = "If this issue persists please visit https://github.com/ultralytics/hub/issues for assistance."
|
|
32
36
|
|
ultralytics/models/nas/model.py
CHANGED
ultralytics/models/rtdetr/val.py
CHANGED
|
@@ -122,8 +122,7 @@ class RTDETRValidator(DetectionValidator):
|
|
|
122
122
|
bbox = ops.xywh2xyxy(bbox) # target boxes
|
|
123
123
|
bbox[..., [0, 2]] *= ori_shape[1] # native-space pred
|
|
124
124
|
bbox[..., [1, 3]] *= ori_shape[0] # native-space pred
|
|
125
|
-
|
|
126
|
-
return prepared_batch
|
|
125
|
+
return dict(cls=cls, bbox=bbox, ori_shape=ori_shape, imgsz=imgsz, ratio_pad=ratio_pad)
|
|
127
126
|
|
|
128
127
|
def _prepare_pred(self, pred, pbatch):
|
|
129
128
|
"""Prepares and returns a batch with transformed bounding boxes and class labels."""
|
ultralytics/models/sam/build.py
CHANGED