ultralytics 8.0.66__py3-none-any.whl → 8.0.68__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 (31) hide show
  1. ultralytics/__init__.py +1 -1
  2. ultralytics/hub/__init__.py +6 -4
  3. ultralytics/hub/auth.py +6 -4
  4. ultralytics/hub/session.py +1 -1
  5. ultralytics/yolo/data/utils.py +2 -2
  6. ultralytics/yolo/engine/exporter.py +8 -3
  7. ultralytics/yolo/engine/model.py +9 -11
  8. ultralytics/yolo/engine/predictor.py +8 -3
  9. ultralytics/yolo/engine/trainer.py +4 -5
  10. ultralytics/yolo/engine/validator.py +8 -3
  11. ultralytics/yolo/utils/__init__.py +16 -5
  12. ultralytics/yolo/utils/callbacks/__init__.py +2 -2
  13. ultralytics/yolo/utils/callbacks/base.py +6 -0
  14. ultralytics/yolo/utils/callbacks/clearml.py +85 -18
  15. ultralytics/yolo/utils/callbacks/comet.py +290 -20
  16. ultralytics/yolo/utils/checks.py +5 -5
  17. ultralytics/yolo/utils/downloads.py +17 -9
  18. ultralytics/yolo/utils/files.py +0 -7
  19. ultralytics/yolo/v8/classify/train.py +2 -2
  20. ultralytics/yolo/v8/classify/val.py +2 -2
  21. ultralytics/yolo/v8/detect/val.py +2 -2
  22. ultralytics/yolo/v8/pose/train.py +2 -2
  23. ultralytics/yolo/v8/pose/val.py +2 -2
  24. ultralytics/yolo/v8/segment/train.py +2 -2
  25. ultralytics/yolo/v8/segment/val.py +2 -2
  26. {ultralytics-8.0.66.dist-info → ultralytics-8.0.68.dist-info}/METADATA +11 -11
  27. {ultralytics-8.0.66.dist-info → ultralytics-8.0.68.dist-info}/RECORD +31 -31
  28. {ultralytics-8.0.66.dist-info → ultralytics-8.0.68.dist-info}/LICENSE +0 -0
  29. {ultralytics-8.0.66.dist-info → ultralytics-8.0.68.dist-info}/WHEEL +0 -0
  30. {ultralytics-8.0.66.dist-info → ultralytics-8.0.68.dist-info}/entry_points.txt +0 -0
  31. {ultralytics-8.0.66.dist-info → ultralytics-8.0.68.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,8 @@
1
1
  # Ultralytics YOLO 🚀, GPL-3.0 license
2
- from ultralytics.yolo.utils import LOGGER, TESTS_RUNNING
2
+ import os
3
+ from pathlib import Path
4
+
5
+ from ultralytics.yolo.utils import LOGGER, RANK, TESTS_RUNNING, ops
3
6
  from ultralytics.yolo.utils.torch_utils import get_flops, get_num_params
4
7
 
5
8
  try:
@@ -10,41 +13,308 @@ try:
10
13
  except (ImportError, AssertionError):
11
14
  comet_ml = None
12
15
 
16
+ COMET_MODE = os.getenv('COMET_MODE', 'online')
17
+ COMET_MODEL_NAME = os.getenv('COMET_MODEL_NAME', 'YOLOv8')
18
+ # determines how many batches of image predictions to log from the validation set
19
+ COMET_EVAL_BATCH_LOGGING_INTERVAL = int(os.getenv('COMET_EVAL_BATCH_LOGGING_INTERVAL', 1))
20
+ # determines whether to log confusion matrix every evaluation epoch
21
+ COMET_EVAL_LOG_CONFUSION_MATRIX = (os.getenv('COMET_EVAL_LOG_CONFUSION_MATRIX', 'true').lower() == 'true')
22
+ # determines whether to log image predictions every evaluation epoch
23
+ COMET_EVAL_LOG_IMAGE_PREDICTIONS = (os.getenv('COMET_EVAL_LOG_IMAGE_PREDICTIONS', 'true').lower() == 'true')
24
+ COMET_MAX_IMAGE_PREDICTIONS = int(os.getenv('COMET_MAX_IMAGE_PREDICTIONS', 100))
13
25
 
14
- def on_pretrain_routine_start(trainer):
26
+ # ensures certain logging functions only run for supported tasks
27
+ COMET_SUPPORTED_TASKS = ['detect']
28
+ # scales reported confidence scores (0.0-1.0) by this value
29
+ COMET_MAX_CONFIDENCE_SCORE = int(os.getenv('COMET_MAX_CONFIDENCE_SCORE', 100))
30
+
31
+ # names of plots created by YOLOv8 that are logged to Comet
32
+ EVALUATION_PLOT_NAMES = 'F1_curve', 'P_curve', 'R_curve', 'PR_curve', 'confusion_matrix'
33
+ LABEL_PLOT_NAMES = 'labels', 'labels_correlogram'
34
+
35
+ _comet_image_prediction_count = 0
36
+
37
+
38
+ def _get_experiment_type(mode, project_name):
39
+ if mode == 'offline':
40
+ return comet_ml.OfflineExperiment(project_name=project_name)
41
+
42
+ return comet_ml.Experiment(project_name=project_name)
43
+
44
+
45
+ def _create_experiment(args):
46
+ # Ensures that the experiment object is only created in a single process during distributed training.
47
+ if RANK not in (-1, 0):
48
+ return
15
49
  try:
16
- experiment = comet_ml.Experiment(project_name=trainer.args.project or 'YOLOv8')
17
- experiment.set_name(trainer.args.name)
18
- experiment.log_parameters(vars(trainer.args))
50
+ experiment = _get_experiment_type(COMET_MODE, args.project)
51
+ experiment.log_parameters(vars(args))
52
+ experiment.log_others({
53
+ 'eval_batch_logging_interval': COMET_EVAL_BATCH_LOGGING_INTERVAL,
54
+ 'log_confusion_matrix': COMET_EVAL_LOG_CONFUSION_MATRIX,
55
+ 'log_image_predictions': COMET_EVAL_LOG_IMAGE_PREDICTIONS,
56
+ 'max_image_predictions': COMET_MAX_IMAGE_PREDICTIONS, })
57
+ experiment.log_other('Created from', 'yolov8')
58
+
19
59
  except Exception as e:
20
60
  LOGGER.warning(f'WARNING ⚠️ Comet installed but not initialized correctly, not logging this run. {e}')
21
61
 
22
62
 
63
+ def _fetch_trainer_metadata(trainer):
64
+ curr_epoch = trainer.epoch + 1
65
+
66
+ train_num_steps_per_epoch = len(trainer.train_loader.dataset) // trainer.batch_size
67
+ curr_step = curr_epoch * train_num_steps_per_epoch
68
+ final_epoch = curr_epoch == trainer.epochs
69
+
70
+ save = trainer.args.save
71
+ save_period = trainer.args.save_period
72
+ save_interval = curr_epoch % save_period == 0
73
+ save_assets = save and save_period > 0 and save_interval and not final_epoch
74
+
75
+ return dict(curr_epoch=curr_epoch, curr_step=curr_step, save_assets=save_assets, final_epoch=final_epoch)
76
+
77
+
78
+ def _scale_bounding_box_to_original_image_shape(box, resized_image_shape, original_image_shape, ratio_pad):
79
+ """YOLOv8 resizes images during training and the label values
80
+ are normalized based on this resized shape. This function rescales the
81
+ bounding box labels to the original image shape.
82
+ """
83
+
84
+ resized_image_height, resized_image_width = resized_image_shape
85
+
86
+ # convert normalized xywh format predictions to xyxy in resized scale format
87
+ box = ops.xywhn2xyxy(box, h=resized_image_height, w=resized_image_width)
88
+ # scale box predictions from resized image scale back to original image scale
89
+ box = ops.scale_boxes(resized_image_shape, box, original_image_shape, ratio_pad)
90
+ # Convert bounding box format from xyxy to xywh for Comet logging
91
+ box = ops.xyxy2xywh(box)
92
+ # adjust xy center to correspond top-left corner
93
+ box[:2] -= box[2:] / 2
94
+ box = box.tolist()
95
+
96
+ return box
97
+
98
+
99
+ def _format_ground_truth_annotations_for_detection(img_idx, image_path, batch, class_name_map=None):
100
+ indices = batch['batch_idx'] == img_idx
101
+ bboxes = batch['bboxes'][indices]
102
+ if len(bboxes) == 0:
103
+ LOGGER.debug(f'COMET WARNING: Image: {image_path} has no bounding boxes labels')
104
+ return None
105
+
106
+ cls_labels = batch['cls'][indices].squeeze(1).tolist()
107
+ if class_name_map:
108
+ cls_labels = [str(class_name_map[label]) for label in cls_labels]
109
+
110
+ original_image_shape = batch['ori_shape'][img_idx]
111
+ resized_image_shape = batch['resized_shape'][img_idx]
112
+ ratio_pad = batch['ratio_pad'][img_idx]
113
+
114
+ data = []
115
+ for box, label in zip(bboxes, cls_labels):
116
+ box = _scale_bounding_box_to_original_image_shape(box, resized_image_shape, original_image_shape, ratio_pad)
117
+ data.append({'boxes': [box], 'label': f'gt_{label}', 'score': COMET_MAX_CONFIDENCE_SCORE})
118
+
119
+ return {'name': 'ground_truth', 'data': data}
120
+
121
+
122
+ def _format_prediction_annotations_for_detection(image_path, metadata, class_label_map=None):
123
+ stem = image_path.stem
124
+ image_id = int(stem) if stem.isnumeric() else stem
125
+
126
+ predictions = metadata.get(image_id)
127
+ if not predictions:
128
+ LOGGER.debug(f'COMET WARNING: Image: {image_path} has no bounding boxes predictions')
129
+ return None
130
+
131
+ data = []
132
+ for prediction in predictions:
133
+ boxes = prediction['bbox']
134
+ score = prediction['score'] * COMET_MAX_CONFIDENCE_SCORE
135
+ cls_label = prediction['category_id']
136
+ if class_label_map:
137
+ cls_label = str(class_label_map[cls_label])
138
+
139
+ data.append({'boxes': [boxes], 'label': cls_label, 'score': score})
140
+
141
+ return {'name': 'prediction', 'data': data}
142
+
143
+
144
+ def _fetch_annotations(img_idx, image_path, batch, prediction_metadata_map, class_label_map):
145
+ ground_truth_annotations = _format_ground_truth_annotations_for_detection(img_idx, image_path, batch,
146
+ class_label_map)
147
+ prediction_annotations = _format_prediction_annotations_for_detection(image_path, prediction_metadata_map,
148
+ class_label_map)
149
+
150
+ annotations = [
151
+ annotation for annotation in [ground_truth_annotations, prediction_annotations] if annotation is not None]
152
+ return [annotations] if annotations else None
153
+
154
+
155
+ def _create_prediction_metadata_map(model_predictions):
156
+ pred_metadata_map = {}
157
+ for prediction in model_predictions:
158
+ pred_metadata_map.setdefault(prediction['image_id'], [])
159
+ pred_metadata_map[prediction['image_id']].append(prediction)
160
+
161
+ return pred_metadata_map
162
+
163
+
164
+ def _log_confusion_matrix(experiment, trainer, curr_step, curr_epoch):
165
+ conf_mat = trainer.validator.confusion_matrix.matrix
166
+ names = list(trainer.data['names'].values()) + ['background']
167
+ experiment.log_confusion_matrix(
168
+ matrix=conf_mat,
169
+ labels=names,
170
+ max_categories=len(names),
171
+ epoch=curr_epoch,
172
+ step=curr_step,
173
+ )
174
+
175
+
176
+ def _log_images(experiment, image_paths, curr_step, annotations=None):
177
+ if annotations:
178
+ for image_path, annotation in zip(image_paths, annotations):
179
+ experiment.log_image(image_path, name=image_path.stem, step=curr_step, annotations=annotation)
180
+
181
+ else:
182
+ for image_path in image_paths:
183
+ experiment.log_image(image_path, name=image_path.stem, step=curr_step)
184
+
185
+
186
+ def _log_image_predictions(experiment, validator, curr_step):
187
+ global _comet_image_prediction_count
188
+
189
+ task = validator.args.task
190
+ if task not in COMET_SUPPORTED_TASKS:
191
+ return
192
+
193
+ jdict = validator.jdict
194
+ if not jdict:
195
+ return
196
+
197
+ predictions_metadata_map = _create_prediction_metadata_map(jdict)
198
+ dataloader = validator.dataloader
199
+ class_label_map = validator.names
200
+
201
+ for batch_idx, batch in enumerate(dataloader):
202
+ if (batch_idx + 1) % COMET_EVAL_BATCH_LOGGING_INTERVAL != 0:
203
+ continue
204
+
205
+ image_paths = batch['im_file']
206
+ for img_idx, image_path in enumerate(image_paths):
207
+ if _comet_image_prediction_count >= COMET_MAX_IMAGE_PREDICTIONS:
208
+ return
209
+
210
+ image_path = Path(image_path)
211
+ annotations = _fetch_annotations(
212
+ img_idx,
213
+ image_path,
214
+ batch,
215
+ predictions_metadata_map,
216
+ class_label_map,
217
+ )
218
+ _log_images(
219
+ experiment,
220
+ [image_path],
221
+ curr_step,
222
+ annotations=annotations,
223
+ )
224
+ _comet_image_prediction_count += 1
225
+
226
+
227
+ def _log_plots(experiment, trainer):
228
+ plot_filenames = [trainer.save_dir / f'{plots}.png' for plots in EVALUATION_PLOT_NAMES]
229
+ _log_images(experiment, plot_filenames, None)
230
+
231
+ label_plot_filenames = [trainer.save_dir / f'{labels}.jpg' for labels in LABEL_PLOT_NAMES]
232
+ _log_images(experiment, label_plot_filenames, None)
233
+
234
+
235
+ def _log_model(experiment, trainer):
236
+ experiment.log_model(
237
+ COMET_MODEL_NAME,
238
+ file_or_folder=str(trainer.best),
239
+ file_name='best.pt',
240
+ overwrite=True,
241
+ )
242
+
243
+
244
+ def on_pretrain_routine_start(trainer):
245
+ experiment = comet_ml.get_global_experiment()
246
+ if not experiment:
247
+ _create_experiment(trainer.args)
248
+
249
+
23
250
  def on_train_epoch_end(trainer):
24
251
  experiment = comet_ml.get_global_experiment()
25
- if experiment:
26
- experiment.log_metrics(trainer.label_loss_items(trainer.tloss, prefix='train'), step=trainer.epoch + 1)
27
- if trainer.epoch == 1:
28
- for f in trainer.save_dir.glob('train_batch*.jpg'):
29
- experiment.log_image(f, name=f.stem, step=trainer.epoch + 1)
252
+ if not experiment:
253
+ return
254
+
255
+ metadata = _fetch_trainer_metadata(trainer)
256
+ curr_epoch = metadata['curr_epoch']
257
+ curr_step = metadata['curr_step']
258
+
259
+ experiment.log_metrics(
260
+ trainer.label_loss_items(trainer.tloss, prefix='train'),
261
+ step=curr_step,
262
+ epoch=curr_epoch,
263
+ )
264
+
265
+ if curr_epoch == 1:
266
+ _log_images(experiment, trainer.save_dir.glob('train_batch*.jpg'), curr_step)
30
267
 
31
268
 
32
269
  def on_fit_epoch_end(trainer):
33
270
  experiment = comet_ml.get_global_experiment()
34
- if experiment:
35
- experiment.log_metrics(trainer.metrics, step=trainer.epoch + 1)
36
- if trainer.epoch == 0:
37
- model_info = {
38
- 'model/parameters': get_num_params(trainer.model),
39
- 'model/GFLOPs': round(get_flops(trainer.model), 3),
40
- 'model/speed(ms)': round(trainer.validator.speed['inference'], 3)}
41
- experiment.log_metrics(model_info, step=trainer.epoch + 1)
271
+ if not experiment:
272
+ return
273
+
274
+ metadata = _fetch_trainer_metadata(trainer)
275
+ curr_epoch = metadata['curr_epoch']
276
+ curr_step = metadata['curr_step']
277
+ save_assets = metadata['save_assets']
278
+
279
+ experiment.log_metrics(trainer.metrics, step=curr_step, epoch=curr_epoch)
280
+ experiment.log_metrics(trainer.lr, step=curr_step, epoch=curr_epoch)
281
+ if curr_epoch == 1:
282
+ model_info = {
283
+ 'model/parameters': get_num_params(trainer.model),
284
+ 'model/GFLOPs': round(get_flops(trainer.model), 3),
285
+ 'model/speed(ms)': round(trainer.validator.speed['inference'], 3)}
286
+ experiment.log_metrics(model_info, step=curr_step, epoch=curr_epoch)
287
+
288
+ if not save_assets:
289
+ return
290
+
291
+ _log_model(experiment, trainer)
292
+ if COMET_EVAL_LOG_CONFUSION_MATRIX:
293
+ _log_confusion_matrix(experiment, trainer, curr_step, curr_epoch)
294
+ if COMET_EVAL_LOG_IMAGE_PREDICTIONS:
295
+ _log_image_predictions(experiment, trainer.validator, curr_step)
42
296
 
43
297
 
44
298
  def on_train_end(trainer):
45
299
  experiment = comet_ml.get_global_experiment()
46
- if experiment:
47
- experiment.log_model('YOLOv8', file_or_folder=str(trainer.best), file_name='best.pt', overwrite=True)
300
+ if not experiment:
301
+ return
302
+
303
+ metadata = _fetch_trainer_metadata(trainer)
304
+ curr_epoch = metadata['curr_epoch']
305
+ curr_step = metadata['curr_step']
306
+ plots = trainer.args.plots
307
+
308
+ _log_model(experiment, trainer)
309
+ if plots:
310
+ _log_plots(experiment, trainer)
311
+
312
+ _log_confusion_matrix(experiment, trainer, curr_step, curr_epoch)
313
+ _log_image_predictions(experiment, trainer.validator, curr_step)
314
+ experiment.end()
315
+
316
+ global _comet_image_prediction_count
317
+ _comet_image_prediction_count = 0
48
318
 
49
319
 
50
320
  callbacks = {
@@ -8,7 +8,6 @@ import platform
8
8
  import re
9
9
  import shutil
10
10
  import subprocess
11
- import urllib
12
11
  from pathlib import Path
13
12
  from typing import Optional
14
13
 
@@ -20,8 +19,9 @@ import requests
20
19
  import torch
21
20
  from matplotlib import font_manager
22
21
 
23
- from ultralytics.yolo.utils import (AUTOINSTALL, LOGGER, ONLINE, ROOT, USER_CONFIG_DIR, TryExcept, colorstr, downloads,
24
- emojis, is_colab, is_docker, is_kaggle, is_online, is_pip_package)
22
+ from ultralytics.yolo.utils import (AUTOINSTALL, LOGGER, ONLINE, ROOT, USER_CONFIG_DIR, TryExcept, clean_url, colorstr,
23
+ downloads, emojis, is_colab, is_docker, is_kaggle, is_online, is_pip_package,
24
+ url2file)
25
25
 
26
26
 
27
27
  def is_ascii(s) -> bool:
@@ -267,9 +267,9 @@ def check_file(file, suffix='', download=True, hard=True):
267
267
  return file
268
268
  elif download and file.lower().startswith(('https://', 'http://', 'rtsp://', 'rtmp://')): # download
269
269
  url = file # warning: Pathlib turns :// -> :/
270
- file = Path(urllib.parse.unquote(file).split('?')[0]).name # '%2F' to '/', split https://url.com/file.txt?auth
270
+ file = url2file(file) # '%2F' to '/', split https://url.com/file.txt?auth
271
271
  if Path(file).exists():
272
- LOGGER.info(f'Found {url} locally at {file}') # file already exists
272
+ LOGGER.info(f'Found {clean_url(url)} locally at {file}') # file already exists
273
273
  else:
274
274
  downloads.safe_download(url=url, file=file, unzip=False)
275
275
  return file
@@ -12,7 +12,7 @@ import requests
12
12
  import torch
13
13
  from tqdm import tqdm
14
14
 
15
- from ultralytics.yolo.utils import LOGGER, checks, emojis, is_online
15
+ from ultralytics.yolo.utils import LOGGER, checks, clean_url, emojis, is_online, url2file
16
16
 
17
17
  GITHUB_ASSET_NAMES = [f'yolov8{k}{suffix}.pt' for k in 'nsmlx' for suffix in ('', '6', '-cls', '-seg', '-pose')] + \
18
18
  [f'yolov5{k}u.pt' for k in 'nsmlx'] + \
@@ -43,10 +43,18 @@ def unzip_file(file, path=None, exclude=('.DS_Store', '__MACOSX')):
43
43
  if path is None:
44
44
  path = Path(file).parent # default path
45
45
  with ZipFile(file) as zipObj:
46
- for f in zipObj.namelist(): # list all archived filenames in the zip
46
+ for i, f in enumerate(zipObj.namelist()): # list all archived filenames in the zip
47
+ # If zip does not expand into a directory create a new directory to expand into
48
+ if i == 0:
49
+ info = zipObj.getinfo(f)
50
+ if info.file_size > 0 or not info.filename.endswith('/'): # element is a file and not a directory
51
+ path = Path(path) / Path(file).stem # define new unzip directory
52
+ unzip_dir = path
53
+ else:
54
+ unzip_dir = f
47
55
  if all(x not in f for x in exclude):
48
56
  zipObj.extract(f, path=path)
49
- return zipObj.namelist()[0] # return unzip dir
57
+ return unzip_dir # return unzip dir
50
58
 
51
59
 
52
60
  def safe_download(url,
@@ -79,8 +87,8 @@ def safe_download(url,
79
87
  f = Path(url) # filename
80
88
  else: # does not exist
81
89
  assert dir or file, 'dir or file required for download'
82
- f = dir / Path(url).name if dir else Path(file)
83
- desc = f'Downloading {url} to {f}'
90
+ f = dir / url2file(url) if dir else Path(file)
91
+ desc = f'Downloading {clean_url(url)} to {f}'
84
92
  LOGGER.info(f'{desc}...')
85
93
  f.parent.mkdir(parents=True, exist_ok=True) # make directory if missing
86
94
  for i in range(retry + 1):
@@ -118,10 +126,10 @@ def safe_download(url,
118
126
  raise ConnectionError(emojis(f'❌ Download failure for {url}. Retry limit reached.')) from e
119
127
  LOGGER.warning(f'⚠️ Download failure, retrying {i + 1}/{retry} {url}...')
120
128
 
121
- if unzip and f.exists() and f.suffix in ('.zip', '.tar', '.gz'):
129
+ if unzip and f.exists() and f.suffix in ('', '.zip', '.tar', '.gz'):
122
130
  unzip_dir = dir or f.parent # unzip to dir if provided else unzip in place
123
131
  LOGGER.info(f'Unzipping {f} to {unzip_dir}...')
124
- if f.suffix == '.zip':
132
+ if is_zipfile(f):
125
133
  unzip_dir = unzip_file(file=f, path=unzip_dir) # unzip
126
134
  elif f.suffix == '.tar':
127
135
  subprocess.run(['tar', 'xf', f, '--directory', unzip_dir], check=True) # unzip
@@ -156,9 +164,9 @@ def attempt_download_asset(file, repo='ultralytics/assets', release='v0.0.0'):
156
164
  name = Path(parse.unquote(str(file))).name # decode '%2F' to '/' etc.
157
165
  if str(file).startswith(('http:/', 'https:/')): # download
158
166
  url = str(file).replace(':/', '://') # Pathlib turns :// -> :/
159
- file = name.split('?')[0] # parse authentication https://url.com/file.txt?auth...
167
+ file = url2file(name) # parse authentication https://url.com/file.txt?auth...
160
168
  if Path(file).is_file():
161
- LOGGER.info(f'Found {url} locally at {file}') # file already exists
169
+ LOGGER.info(f'Found {clean_url(url)} locally at {file}') # file already exists
162
170
  else:
163
171
  safe_download(url=url, file=file, min_bytes=1E5)
164
172
  return file
@@ -3,7 +3,6 @@
3
3
  import contextlib
4
4
  import glob
5
5
  import os
6
- import urllib
7
6
  from datetime import datetime
8
7
  from pathlib import Path
9
8
 
@@ -80,12 +79,6 @@ def file_size(path):
80
79
  return 0.0
81
80
 
82
81
 
83
- def url2file(url):
84
- # Convert URL to filename, i.e. https://url.com/file.txt?auth -> file.txt
85
- url = str(Path(url)).replace(':/', '://') # Pathlib turns :// -> :/
86
- return Path(urllib.parse.unquote(url)).name.split('?')[0] # '%2F' to '/', split https://url.com/file.txt?auth
87
-
88
-
89
82
  def get_latest_run(search_dir='.'):
90
83
  # Return path to most recent 'last.pt' in /runs (i.e. to --resume from)
91
84
  last_list = glob.glob(f'{search_dir}/**/last*.pt', recursive=True)
@@ -13,11 +13,11 @@ from ultralytics.yolo.utils.torch_utils import is_parallel, strip_optimizer
13
13
 
14
14
  class ClassificationTrainer(BaseTrainer):
15
15
 
16
- def __init__(self, cfg=DEFAULT_CFG, overrides=None):
16
+ def __init__(self, cfg=DEFAULT_CFG, overrides=None, _callbacks=None):
17
17
  if overrides is None:
18
18
  overrides = {}
19
19
  overrides['task'] = 'classify'
20
- super().__init__(cfg, overrides)
20
+ super().__init__(cfg, overrides, _callbacks)
21
21
 
22
22
  def set_model_attributes(self):
23
23
  self.model.names = self.data['names']
@@ -8,8 +8,8 @@ from ultralytics.yolo.utils.metrics import ClassifyMetrics
8
8
 
9
9
  class ClassificationValidator(BaseValidator):
10
10
 
11
- def __init__(self, dataloader=None, save_dir=None, pbar=None, args=None):
12
- super().__init__(dataloader, save_dir, pbar, args)
11
+ def __init__(self, dataloader=None, save_dir=None, pbar=None, args=None, _callbacks=None):
12
+ super().__init__(dataloader, save_dir, pbar, args, _callbacks)
13
13
  self.args.task = 'classify'
14
14
  self.metrics = ClassifyMetrics()
15
15
 
@@ -18,8 +18,8 @@ from ultralytics.yolo.utils.torch_utils import de_parallel
18
18
 
19
19
  class DetectionValidator(BaseValidator):
20
20
 
21
- def __init__(self, dataloader=None, save_dir=None, pbar=None, args=None):
22
- super().__init__(dataloader, save_dir, pbar, args)
21
+ def __init__(self, dataloader=None, save_dir=None, pbar=None, args=None, _callbacks=None):
22
+ super().__init__(dataloader, save_dir, pbar, args, _callbacks)
23
23
  self.args.task = 'detect'
24
24
  self.is_coco = False
25
25
  self.class_map = None
@@ -20,11 +20,11 @@ from ultralytics.yolo.v8.detect.train import Loss
20
20
  # BaseTrainer python usage
21
21
  class PoseTrainer(v8.detect.DetectionTrainer):
22
22
 
23
- def __init__(self, cfg=DEFAULT_CFG, overrides=None):
23
+ def __init__(self, cfg=DEFAULT_CFG, overrides=None, _callbacks=None):
24
24
  if overrides is None:
25
25
  overrides = {}
26
26
  overrides['task'] = 'pose'
27
- super().__init__(cfg, overrides)
27
+ super().__init__(cfg, overrides, _callbacks)
28
28
 
29
29
  def get_model(self, cfg=None, weights=None, verbose=True):
30
30
  model = PoseModel(cfg, ch=3, nc=self.data['nc'], data_kpt_shape=self.data['kpt_shape'], verbose=verbose)
@@ -14,8 +14,8 @@ from ultralytics.yolo.v8.detect import DetectionValidator
14
14
 
15
15
  class PoseValidator(DetectionValidator):
16
16
 
17
- def __init__(self, dataloader=None, save_dir=None, pbar=None, args=None):
18
- super().__init__(dataloader, save_dir, pbar, args)
17
+ def __init__(self, dataloader=None, save_dir=None, pbar=None, args=None, _callbacks=None):
18
+ super().__init__(dataloader, save_dir, pbar, args, _callbacks)
19
19
  self.args.task = 'pose'
20
20
  self.metrics = PoseMetrics(save_dir=self.save_dir)
21
21
 
@@ -17,11 +17,11 @@ from ultralytics.yolo.v8.detect.train import Loss
17
17
  # BaseTrainer python usage
18
18
  class SegmentationTrainer(v8.detect.DetectionTrainer):
19
19
 
20
- def __init__(self, cfg=DEFAULT_CFG, overrides=None):
20
+ def __init__(self, cfg=DEFAULT_CFG, overrides=None, _callbacks=None):
21
21
  if overrides is None:
22
22
  overrides = {}
23
23
  overrides['task'] = 'segment'
24
- super().__init__(cfg, overrides)
24
+ super().__init__(cfg, overrides, _callbacks)
25
25
 
26
26
  def get_model(self, cfg=None, weights=None, verbose=True):
27
27
  model = SegmentationModel(cfg, ch=3, nc=self.data['nc'], verbose=verbose and RANK == -1)
@@ -16,8 +16,8 @@ from ultralytics.yolo.v8.detect import DetectionValidator
16
16
 
17
17
  class SegmentationValidator(DetectionValidator):
18
18
 
19
- def __init__(self, dataloader=None, save_dir=None, pbar=None, args=None):
20
- super().__init__(dataloader, save_dir, pbar, args)
19
+ def __init__(self, dataloader=None, save_dir=None, pbar=None, args=None, _callbacks=None):
20
+ super().__init__(dataloader, save_dir, pbar, args, _callbacks)
21
21
  self.args.task = 'segment'
22
22
  self.metrics = SegmentMetrics(save_dir=self.save_dir)
23
23
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ultralytics
3
- Version: 8.0.66
3
+ Version: 8.0.68
4
4
  Summary: Ultralytics YOLOv8
5
5
  Home-page: https://github.com/ultralytics/ultralytics
6
6
  Author: Ultralytics
@@ -250,12 +250,12 @@ See [Pose Docs](https://docs.ultralytics.com/tasks/) for usage examples with the
250
250
 
251
251
  | Model | size<br><sup>(pixels) | mAP<sup>box<br>50-95 | mAP<sup>pose<br>50-95 | Speed<br><sup>CPU ONNX<br>(ms) | Speed<br><sup>A100 TensorRT<br>(ms) | params<br><sup>(M) | FLOPs<br><sup>(B) |
252
252
  | ---------------------------------------------------------------------------------------------------- | --------------------- | -------------------- | --------------------- | ------------------------------ | ----------------------------------- | ------------------ | ----------------- |
253
- | [YOLOv8n-pose](https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8n-pose.pt) | 640 | - | 49.7 | - | - | 3.3 | 9.2 |
254
- | [YOLOv8s-pose](https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8s-pose.pt) | 640 | - | 59.2 | - | - | 11.6 | 30.2 |
255
- | [YOLOv8m-pose](https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8m-pose.pt) | 640 | - | 63.6 | - | - | 26.4 | 81.0 |
256
- | [YOLOv8l-pose](https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8l-pose.pt) | 640 | - | 67.0 | - | - | 44.4 | 168.6 |
257
- | [YOLOv8x-pose](https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8x-pose.pt) | 640 | - | 68.9 | - | - | 69.4 | 263.2 |
258
- | [YOLOv8x-pose-p6](https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8x-pose-p6.pt) | 1280 | - | 71.5 | - | - | 99.1 | 1066.4 |
253
+ | [YOLOv8n-pose](https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8n-pose.pt) | 640 | - | 49.7 | 131.8 | 1.18 | 3.3 | 9.2 |
254
+ | [YOLOv8s-pose](https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8s-pose.pt) | 640 | - | 59.2 | 233.2 | 1.42 | 11.6 | 30.2 |
255
+ | [YOLOv8m-pose](https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8m-pose.pt) | 640 | - | 63.6 | 456.3 | 2.00 | 26.4 | 81.0 |
256
+ | [YOLOv8l-pose](https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8l-pose.pt) | 640 | - | 67.0 | 784.5 | 2.59 | 44.4 | 168.6 |
257
+ | [YOLOv8x-pose](https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8x-pose.pt) | 640 | - | 68.9 | 1607.1 | 3.73 | 69.4 | 263.2 |
258
+ | [YOLOv8x-pose-p6](https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8x-pose-p6.pt) | 1280 | - | 71.5 | 4088.7 | 10.04 | 99.1 | 1066.4 |
259
259
 
260
260
  - **mAP<sup>val</sup>** values are for single-model single-scale on [COCO Keypoints val2017](http://cocodataset.org)
261
261
  dataset.
@@ -281,16 +281,16 @@ See [Pose Docs](https://docs.ultralytics.com/tasks/) for usage examples with the
281
281
  <a href="https://cutt.ly/yolov5-readme-clearml">
282
282
  <img src="https://github.com/ultralytics/assets/raw/main/partners/logo-clearml.png" width="10%" /></a>
283
283
  <img src="https://github.com/ultralytics/assets/raw/main/social/logo-transparent.png" width="15%" height="0" alt="" />
284
- <a href="https://bit.ly/yolov5-readme-comet2">
284
+ <a href="https://bit.ly/yolov8-readme-comet">
285
285
  <img src="https://github.com/ultralytics/assets/raw/main/partners/logo-comet.png" width="10%" /></a>
286
286
  <img src="https://github.com/ultralytics/assets/raw/main/social/logo-transparent.png" width="15%" height="0" alt="" />
287
287
  <a href="https://bit.ly/yolov5-neuralmagic">
288
288
  <img src="https://github.com/ultralytics/assets/raw/main/partners/logo-neuralmagic.png" width="10%" /></a>
289
289
  </div>
290
290
 
291
- | Roboflow | ClearML ⭐ NEW | Comet ⭐ NEW | Neural Magic ⭐ NEW |
292
- | :--------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------: |
293
- | Label and export your custom datasets directly to YOLOv8 for training with [Roboflow](https://roboflow.com/?ref=ultralytics) | Automatically track, visualize and even remotely train YOLOv8 using [ClearML](https://cutt.ly/yolov5-readme-clearml) (open-source!) | Free forever, [Comet](https://bit.ly/yolov5-readme-comet2) lets you save YOLOv8 models, resume training, and interactively visualize and debug predictions | Run YOLOv8 inference up to 6x faster with [Neural Magic DeepSparse](https://bit.ly/yolov5-neuralmagic) |
291
+ | Roboflow | ClearML ⭐ NEW | Comet ⭐ NEW | Neural Magic ⭐ NEW |
292
+ | :--------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------: |
293
+ | Label and export your custom datasets directly to YOLOv8 for training with [Roboflow](https://roboflow.com/?ref=ultralytics) | Automatically track, visualize and even remotely train YOLOv8 using [ClearML](https://cutt.ly/yolov5-readme-clearml) (open-source!) | Free forever, [Comet](https://bit.ly/yolov8-readme-comet) lets you save YOLOv8 models, resume training, and interactively visualize and debug predictions | Run YOLOv8 inference up to 6x faster with [Neural Magic DeepSparse](https://bit.ly/yolov5-neuralmagic) |
294
294
 
295
295
  ## <div align="center">Ultralytics HUB</div>
296
296