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.

Files changed (105) hide show
  1. ultralytics/__init__.py +1 -1
  2. ultralytics/cfg/__init__.py +1 -1
  3. ultralytics/cfg/datasets/Argoverse.yaml +5 -7
  4. ultralytics/cfg/datasets/DOTAv1.5.yaml +4 -4
  5. ultralytics/cfg/datasets/DOTAv1.yaml +4 -4
  6. ultralytics/cfg/datasets/GlobalWheat2020.yaml +2 -4
  7. ultralytics/cfg/datasets/ImageNet.yaml +4 -6
  8. ultralytics/cfg/datasets/Objects365.yaml +3 -5
  9. ultralytics/cfg/datasets/SKU-110K.yaml +4 -6
  10. ultralytics/cfg/datasets/VOC.yaml +0 -2
  11. ultralytics/cfg/datasets/VisDrone.yaml +4 -6
  12. ultralytics/cfg/datasets/coco-pose.yaml +6 -7
  13. ultralytics/cfg/datasets/coco.yaml +5 -7
  14. ultralytics/cfg/datasets/coco128-seg.yaml +4 -6
  15. ultralytics/cfg/datasets/coco128.yaml +4 -6
  16. ultralytics/cfg/datasets/coco8-pose.yaml +5 -6
  17. ultralytics/cfg/datasets/coco8-seg.yaml +4 -6
  18. ultralytics/cfg/datasets/coco8.yaml +4 -6
  19. ultralytics/cfg/datasets/dota8.yaml +3 -3
  20. ultralytics/cfg/datasets/open-images-v7.yaml +4 -6
  21. ultralytics/cfg/datasets/tiger-pose.yaml +4 -5
  22. ultralytics/cfg/datasets/xView.yaml +3 -5
  23. ultralytics/cfg/default.yaml +103 -103
  24. ultralytics/cfg/models/rt-detr/rtdetr-l.yaml +27 -27
  25. ultralytics/cfg/models/rt-detr/rtdetr-resnet101.yaml +23 -23
  26. ultralytics/cfg/models/rt-detr/rtdetr-resnet50.yaml +23 -23
  27. ultralytics/cfg/models/rt-detr/rtdetr-x.yaml +27 -27
  28. ultralytics/cfg/models/v3/yolov3-spp.yaml +32 -34
  29. ultralytics/cfg/models/v3/yolov3-tiny.yaml +24 -26
  30. ultralytics/cfg/models/v3/yolov3.yaml +32 -34
  31. ultralytics/cfg/models/v5/yolov5-p6.yaml +41 -43
  32. ultralytics/cfg/models/v5/yolov5.yaml +26 -28
  33. ultralytics/cfg/models/v6/yolov6.yaml +17 -17
  34. ultralytics/cfg/models/v8/yolov8-cls-resnet101.yaml +25 -0
  35. ultralytics/cfg/models/v8/yolov8-cls-resnet50.yaml +25 -0
  36. ultralytics/cfg/models/v8/yolov8-cls.yaml +7 -7
  37. ultralytics/cfg/models/v8/yolov8-ghost-p2.yaml +26 -26
  38. ultralytics/cfg/models/v8/yolov8-ghost-p6.yaml +27 -27
  39. ultralytics/cfg/models/v8/yolov8-ghost.yaml +23 -23
  40. ultralytics/cfg/models/v8/yolov8-obb.yaml +23 -23
  41. ultralytics/cfg/models/v8/yolov8-p2.yaml +23 -23
  42. ultralytics/cfg/models/v8/yolov8-p6.yaml +24 -24
  43. ultralytics/cfg/models/v8/yolov8-pose-p6.yaml +25 -25
  44. ultralytics/cfg/models/v8/yolov8-pose.yaml +19 -19
  45. ultralytics/cfg/models/v8/yolov8-rtdetr.yaml +23 -23
  46. ultralytics/cfg/models/v8/yolov8-seg-p6.yaml +24 -24
  47. ultralytics/cfg/models/v8/yolov8-seg.yaml +18 -18
  48. ultralytics/cfg/models/v8/yolov8.yaml +23 -23
  49. ultralytics/cfg/trackers/botsort.yaml +7 -7
  50. ultralytics/cfg/trackers/bytetrack.yaml +6 -6
  51. ultralytics/data/annotator.py +1 -1
  52. ultralytics/data/augment.py +1 -2
  53. ultralytics/data/base.py +0 -1
  54. ultralytics/data/build.py +1 -2
  55. ultralytics/data/dataset.py +0 -1
  56. ultralytics/data/explorer/explorer.py +11 -12
  57. ultralytics/data/explorer/utils.py +3 -3
  58. ultralytics/data/split_dota.py +15 -23
  59. ultralytics/engine/model.py +12 -11
  60. ultralytics/engine/predictor.py +1 -1
  61. ultralytics/engine/trainer.py +1 -4
  62. ultralytics/hub/__init__.py +5 -3
  63. ultralytics/hub/auth.py +1 -2
  64. ultralytics/hub/session.py +14 -6
  65. ultralytics/hub/utils.py +4 -0
  66. ultralytics/models/fastsam/model.py +0 -1
  67. ultralytics/models/nas/model.py +0 -1
  68. ultralytics/models/rtdetr/train.py +0 -1
  69. ultralytics/models/rtdetr/val.py +1 -2
  70. ultralytics/models/sam/build.py +0 -1
  71. ultralytics/models/sam/model.py +0 -1
  72. ultralytics/models/sam/modules/encoders.py +1 -6
  73. ultralytics/models/sam/predict.py +0 -1
  74. ultralytics/models/utils/loss.py +0 -1
  75. ultralytics/models/yolo/detect/val.py +1 -2
  76. ultralytics/models/yolo/obb/val.py +14 -39
  77. ultralytics/nn/modules/head.py +5 -6
  78. ultralytics/nn/modules/utils.py +1 -1
  79. ultralytics/nn/tasks.py +1 -1
  80. ultralytics/solutions/ai_gym.py +9 -1
  81. ultralytics/solutions/distance_calculation.py +4 -8
  82. ultralytics/solutions/heatmap.py +16 -21
  83. ultralytics/solutions/object_counter.py +30 -29
  84. ultralytics/solutions/speed_estimation.py +19 -24
  85. ultralytics/trackers/track.py +0 -1
  86. ultralytics/trackers/utils/gmc.py +1 -1
  87. ultralytics/trackers/utils/matching.py +1 -3
  88. ultralytics/utils/benchmarks.py +2 -7
  89. ultralytics/utils/callbacks/base.py +1 -0
  90. ultralytics/utils/callbacks/comet.py +4 -22
  91. ultralytics/utils/callbacks/hub.py +1 -3
  92. ultralytics/utils/callbacks/neptune.py +1 -3
  93. ultralytics/utils/callbacks/tensorboard.py +2 -1
  94. ultralytics/utils/checks.py +2 -2
  95. ultralytics/utils/loss.py +3 -6
  96. ultralytics/utils/ops.py +8 -9
  97. ultralytics/utils/plotting.py +13 -15
  98. ultralytics/utils/tal.py +1 -2
  99. {ultralytics-8.1.1.dist-info → ultralytics-8.1.3.dist-info}/METADATA +15 -15
  100. ultralytics-8.1.3.dist-info/RECORD +190 -0
  101. ultralytics-8.1.1.dist-info/RECORD +0 -188
  102. {ultralytics-8.1.1.dist-info → ultralytics-8.1.3.dist-info}/LICENSE +0 -0
  103. {ultralytics-8.1.1.dist-info → ultralytics-8.1.3.dist-info}/WHEEL +0 -0
  104. {ultralytics-8.1.1.dist-info → ultralytics-8.1.3.dist-info}/entry_points.txt +0 -0
  105. {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 # number of classes
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] # 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
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]] # 0-P1/2
18
- - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
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]] # 3-P3/8
20
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
21
21
  - [-1, 6, C2f, [256, True]]
22
- - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
22
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
23
23
  - [-1, 6, C2f, [512, True]]
24
- - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
24
+ - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
25
25
  - [-1, 3, C2f, [1024, True]]
26
- - [-1, 1, SPPF, [1024, 5]] # 9
26
+ - [-1, 1, SPPF, [1024, 5]] # 9
27
27
 
28
28
  # YOLOv8.0n head
29
29
  head:
30
- - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
31
- - [[-1, 6], 1, Concat, [1]] # cat backbone P4
32
- - [-1, 3, C2f, [512]] # 12
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, 'nearest']]
35
- - [[-1, 4], 1, Concat, [1]] # cat backbone P3
36
- - [-1, 3, C2f, [256]] # 15 (P3/8-small)
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]] # cat head P4
40
- - [-1, 3, C2f, [512]] # 18 (P4/16-medium)
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]] # cat head P5
44
- - [-1, 3, C2f, [1024]] # 21 (P5/32-large)
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]] # Detect(P3, P4, P5)
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 # 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
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 # method of global motion compensation
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 # 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
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)
@@ -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"{str(Path(output_dir) / Path(result.path).stem)}.txt", "w") as 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:
@@ -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([math.floor(x / crop_fraction) for x in size])
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
@@ -15,7 +15,6 @@ import psutil
15
15
  from torch.utils.data import Dataset
16
16
 
17
17
  from ultralytics.utils import DEFAULT_CFG, LOCAL_RANK, LOGGER, NUM_THREADS, TQDM
18
-
19
18
  from .utils import HELP_URL, IMG_FORMATS
20
19
 
21
20
 
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), batch, workers]) # number of workers
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)
@@ -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
- ], f"Return type should be either `pandas` or `arrow`, but got {return_type}"
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 == "pandas":
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
- ], f"Return type should be either `pandas` or `arrow`, but got {return_type}"
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 == "pandas":
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 len(plot_masks) > 0 else np.zeros(0, dtype=np.uint8)
102
- kpts = np.concatenate(plot_kpts, axis=0) if len(plot_kpts) > 0 else np.zeros((0, 51), dtype=np.float32)
103
- boxes = xyxy2xywh(np.concatenate(plot_boxes, axis=0)) if len(plot_boxes) > 0 else np.zeros(0, dtype=np.float32)
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
 
@@ -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 = os.path.join(data_root, f"images/{split}")
77
- assert Path(im_dir).exists(), f"Can't find {im_dir}, please check your data root."
78
- im_files = glob(os.path.join(data_root, f"images/{split}/*"))
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 each crops.
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
- window_anns = [(label[iofs[:, i] >= iof_thr]) for i in range(len(windows))]
141
+ return [(label[iofs[:, i] >= iof_thr]) for i in range(len(windows))] # window_anns
143
142
  else:
144
- window_anns = [np.zeros((0, 9), dtype=np.float32) for _ in range(len(windows))]
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 + "__" + str(x_stop - x_start) + "__" + str(x_start) + "___" + str(y_start)
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(os.path.join(im_dir, f"{new_name}.jpg"), patch_im)
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(os.path.join(lb_dir, f"{new_name}.txt"), "w") as f:
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(os.path.join(data_root, "images/test"))
274
- assert im_dir.exists(), f"Can't find {str(im_dir)}, please check your data root."
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 + "__" + str(x_stop - x_start) + "__" + str(x_start) + "___" + str(y_start)
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(os.path.join(str(save_dir), f"{new_name}.jpg"), patch_im)
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
- data_root="DOTAv2",
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")
@@ -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
- ) # MODELID
129
+ )
129
130
 
130
- def _new(self, cfg: str, task=None, model=None, verbose=True):
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 permission error
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
@@ -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):
@@ -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
@@ -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"
@@ -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
- # Initialize model
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
- # Initialize model
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
- # Status codes that trigger retries
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 True if status_code in retry_codes else False
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
 
@@ -3,7 +3,6 @@
3
3
  from pathlib import Path
4
4
 
5
5
  from ultralytics.engine.model import Model
6
-
7
6
  from .predict import FastSAMPredictor
8
7
  from .val import FastSAMValidator
9
8
 
@@ -17,7 +17,6 @@ import torch
17
17
 
18
18
  from ultralytics.engine.model import Model
19
19
  from ultralytics.utils.torch_utils import model_info, smart_inference_mode
20
-
21
20
  from .predict import NASPredictor
22
21
  from .val import NASValidator
23
22
 
@@ -7,7 +7,6 @@ import torch
7
7
  from ultralytics.models.yolo.detect import DetectionTrainer
8
8
  from ultralytics.nn.tasks import RTDETRDetectionModel
9
9
  from ultralytics.utils import RANK, colorstr
10
-
11
10
  from .val import RTDETRDataset, RTDETRValidator
12
11
 
13
12
 
@@ -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
- prepared_batch = dict(cls=cls, bbox=bbox, ori_shape=ori_shape, imgsz=imgsz, ratio_pad=ratio_pad)
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."""
@@ -11,7 +11,6 @@ from functools import partial
11
11
  import torch
12
12
 
13
13
  from ultralytics.utils.downloads import attempt_download_asset
14
-
15
14
  from .modules.decoders import MaskDecoder
16
15
  from .modules.encoders import ImageEncoderViT, PromptEncoder
17
16
  from .modules.sam import Sam