ultralytics 8.3.187__py3-none-any.whl → 8.3.188__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.
ultralytics/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
- __version__ = "8.3.187"
3
+ __version__ = "8.3.188"
4
4
 
5
5
  import os
6
6
 
@@ -582,9 +582,9 @@ class Exporter:
582
582
  @try_export
583
583
  def export_onnx(self, prefix=colorstr("ONNX:")):
584
584
  """Export YOLO model to ONNX format."""
585
- requirements = ["onnx>=1.12.0,<1.18.0"]
585
+ requirements = ["onnx>=1.12.0"]
586
586
  if self.args.simplify:
587
- requirements += ["onnxslim>=0.1.59", "onnxruntime" + ("-gpu" if torch.cuda.is_available() else "")]
587
+ requirements += ["onnxslim>=0.1.65", "onnxruntime" + ("-gpu" if torch.cuda.is_available() else "")]
588
588
  check_requirements(requirements)
589
589
  import onnx # noqa
590
590
 
@@ -960,9 +960,9 @@ class Exporter:
960
960
  "sng4onnx>=1.0.1", # required by 'onnx2tf' package
961
961
  "onnx_graphsurgeon>=0.3.26", # required by 'onnx2tf' package
962
962
  "ai-edge-litert>=1.2.0,<1.4.0", # required by 'onnx2tf' package
963
- "onnx>=1.12.0,<1.18.0",
963
+ "onnx>=1.12.0",
964
964
  "onnx2tf>=1.26.3",
965
- "onnxslim>=0.1.59",
965
+ "onnxslim>=0.1.65",
966
966
  "onnxruntime-gpu" if cuda else "onnxruntime",
967
967
  "protobuf>=5",
968
968
  ),
@@ -196,7 +196,8 @@ class RTDETRValidator(DetectionValidator):
196
196
  with bounding box coordinates, confidence scores, and class predictions.
197
197
  pbatch (Dict[str, Any]): Batch dictionary containing 'imgsz', 'ori_shape', 'ratio_pad', and 'im_file'.
198
198
  """
199
- stem = Path(pbatch["im_file"]).stem
199
+ path = Path(pbatch["im_file"])
200
+ stem = path.stem
200
201
  image_id = int(stem) if stem.isnumeric() else stem
201
202
  box = predn["bboxes"].clone()
202
203
  box[..., [0, 2]] *= pbatch["ori_shape"][1] / self.args.imgsz # native-space pred
@@ -207,6 +208,7 @@ class RTDETRValidator(DetectionValidator):
207
208
  self.jdict.append(
208
209
  {
209
210
  "image_id": image_id,
211
+ "file_name": path.name,
210
212
  "category_id": self.class_map[int(c)],
211
213
  "bbox": [round(x, 3) for x in b],
212
214
  "score": round(s, 5),
@@ -372,8 +372,18 @@ class DetectionValidator(BaseValidator):
372
372
  predn (Dict[str, torch.Tensor]): Predictions dictionary containing 'bboxes', 'conf', and 'cls' keys
373
373
  with bounding box coordinates, confidence scores, and class predictions.
374
374
  pbatch (Dict[str, Any]): Batch dictionary containing 'imgsz', 'ori_shape', 'ratio_pad', and 'im_file'.
375
- """
376
- stem = Path(pbatch["im_file"]).stem
375
+
376
+ Examples:
377
+ >>> result = {
378
+ ... "image_id": 42,
379
+ ... "file_name": "42.jpg",
380
+ ... "category_id": 18,
381
+ ... "bbox": [258.15, 41.29, 348.26, 243.78],
382
+ ... "score": 0.236,
383
+ ... }
384
+ """
385
+ path = Path(pbatch["im_file"])
386
+ stem = path.stem
377
387
  image_id = int(stem) if stem.isnumeric() else stem
378
388
  box = ops.xyxy2xywh(predn["bboxes"]) # xywh
379
389
  box[:, :2] -= box[:, 2:] / 2 # xy center to top-left corner
@@ -381,6 +391,7 @@ class DetectionValidator(BaseValidator):
381
391
  self.jdict.append(
382
392
  {
383
393
  "image_id": image_id,
394
+ "file_name": path.name,
384
395
  "category_id": self.class_map[int(c)],
385
396
  "bbox": [round(x, 3) for x in b],
386
397
  "score": round(s, 5),
@@ -176,7 +176,8 @@ class OBBValidator(DetectionValidator):
176
176
  (x, y, w, h, angle) and polygon format (x1, y1, x2, y2, x3, y3, x4, y4) before adding them
177
177
  to the JSON dictionary.
178
178
  """
179
- stem = Path(pbatch["im_file"]).stem
179
+ path = Path(pbatch["im_file"])
180
+ stem = path.stem
180
181
  image_id = int(stem) if stem.isnumeric() else stem
181
182
  rbox = predn["bboxes"]
182
183
  poly = ops.xywhr2xyxyxyxy(rbox).view(-1, 8)
@@ -184,6 +185,7 @@ class OBBValidator(DetectionValidator):
184
185
  self.jdict.append(
185
186
  {
186
187
  "image_id": image_id,
188
+ "file_name": path.name,
187
189
  "category_id": self.class_map[int(c)],
188
190
  "score": round(s, 5),
189
191
  "rbox": [round(x, 3) for x in r],
@@ -217,9 +217,6 @@ class SegmentationValidator(DetectionValidator):
217
217
  Args:
218
218
  predn (Dict[str, torch.Tensor]): Predictions containing bboxes, masks, confidence scores, and classes.
219
219
  pbatch (Dict[str, Any]): Batch dictionary containing 'imgsz', 'ori_shape', 'ratio_pad', and 'im_file'.
220
-
221
- Examples:
222
- >>> result = {"image_id": 42, "category_id": 18, "bbox": [258.15, 41.29, 348.26, 243.78], "score": 0.236}
223
220
  """
224
221
  from faster_coco_eval.core.mask import encode # noqa
225
222
 
@@ -90,9 +90,13 @@ def benchmark(
90
90
 
91
91
  import polars as pl # scope for faster 'import ultralytics'
92
92
 
93
- pl.Config.set_tbl_cols(10)
94
- pl.Config.set_tbl_width_chars(120)
95
- pl.Config.set_tbl_hide_dataframe_shape(True)
93
+ pl.Config.set_tbl_cols(-1) # Show all columns
94
+ pl.Config.set_tbl_rows(-1) # Show all rows
95
+ pl.Config.set_tbl_width_chars(-1) # No width limit
96
+ pl.Config.set_tbl_hide_column_data_types(True) # Hide data types
97
+ pl.Config.set_tbl_hide_dataframe_shape(True) # Hide shape info
98
+ pl.Config.set_tbl_formatting("ASCII_BORDERS_ONLY_CONDENSED")
99
+
96
100
  device = select_device(device, verbose=False)
97
101
  if isinstance(model, (str, Path)):
98
102
  model = YOLO(model)
@@ -194,12 +198,14 @@ def benchmark(
194
198
 
195
199
  # Print results
196
200
  check_yolo(device=device) # print system info
197
- df = pl.DataFrame(y, schema=["Format", "Status❔", "Size (MB)", key, "Inference time (ms/im)", "FPS"])
201
+ df = pl.DataFrame(y, schema=["Format", "Status❔", "Size (MB)", key, "Inference time (ms/im)", "FPS"], orient="row")
202
+ df = df.with_row_index(" ", offset=1) # add index info
203
+ df_display = df.with_columns(pl.all().cast(pl.String).fill_null("-"))
198
204
 
199
205
  name = model.model_name
200
206
  dt = time.time() - t0
201
207
  legend = "Benchmarks legend: - ✅ Success - ❎ Export passed but validation failed - ❌️ Export failed"
202
- s = f"\nBenchmarks complete for {name} on {data} at imgsz={imgsz} ({dt:.2f}s)\n{legend}\n{df.fill_null('-')}\n"
208
+ s = f"\nBenchmarks complete for {name} on {data} at imgsz={imgsz} ({dt:.2f}s)\n{legend}\n{df_display}\n"
203
209
  LOGGER.info(s)
204
210
  with open("benchmarks.log", "a", errors="ignore", encoding="utf-8") as f:
205
211
  f.write(s)
@@ -209,7 +215,7 @@ def benchmark(
209
215
  floor = verbose # minimum metric floor to pass, i.e. = 0.29 mAP for YOLOv5n
210
216
  assert all(x > floor for x in metrics if not np.isnan(x)), f"Benchmark failure: metric(s) < floor {floor}"
211
217
 
212
- return df
218
+ return df_display
213
219
 
214
220
 
215
221
  class RF100Benchmark:
@@ -1,12 +1,13 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import re
4
6
  import shutil
5
7
  import subprocess
6
8
  from itertools import repeat
7
9
  from multiprocessing.pool import ThreadPool
8
10
  from pathlib import Path
9
- from typing import List, Tuple
10
11
  from urllib import parse, request
11
12
 
12
13
  from ultralytics.utils import LOGGER, TQDM, checks, clean_url, emojis, is_online, url2file
@@ -41,7 +42,7 @@ GITHUB_ASSETS_NAMES = frozenset(
41
42
  GITHUB_ASSETS_STEMS = frozenset(k.rpartition(".")[0] for k in GITHUB_ASSETS_NAMES)
42
43
 
43
44
 
44
- def is_url(url, check: bool = False) -> bool:
45
+ def is_url(url: str | Path, check: bool = False) -> bool:
45
46
  """
46
47
  Validate if the given string is a URL and optionally check if the URL exists online.
47
48
 
@@ -68,7 +69,7 @@ def is_url(url, check: bool = False) -> bool:
68
69
  return False
69
70
 
70
71
 
71
- def delete_dsstore(path, files_to_delete=(".DS_Store", "__MACOSX")):
72
+ def delete_dsstore(path: str | Path, files_to_delete: tuple[str, ...] = (".DS_Store", "__MACOSX")) -> None:
72
73
  """
73
74
  Delete all specified system files in a directory.
74
75
 
@@ -91,7 +92,12 @@ def delete_dsstore(path, files_to_delete=(".DS_Store", "__MACOSX")):
91
92
  f.unlink()
92
93
 
93
94
 
94
- def zip_directory(directory, compress: bool = True, exclude=(".DS_Store", "__MACOSX"), progress: bool = True) -> Path:
95
+ def zip_directory(
96
+ directory: str | Path,
97
+ compress: bool = True,
98
+ exclude: tuple[str, ...] = (".DS_Store", "__MACOSX"),
99
+ progress: bool = True,
100
+ ) -> Path:
95
101
  """
96
102
  Zip the contents of a directory, excluding specified files.
97
103
 
@@ -129,9 +135,9 @@ def zip_directory(directory, compress: bool = True, exclude=(".DS_Store", "__MAC
129
135
 
130
136
 
131
137
  def unzip_file(
132
- file,
133
- path=None,
134
- exclude=(".DS_Store", "__MACOSX"),
138
+ file: str | Path,
139
+ path: str | Path | None = None,
140
+ exclude: tuple[str, ...] = (".DS_Store", "__MACOSX"),
135
141
  exist_ok: bool = False,
136
142
  progress: bool = True,
137
143
  ) -> Path:
@@ -198,8 +204,8 @@ def unzip_file(
198
204
 
199
205
 
200
206
  def check_disk_space(
201
- url: str = "https://ultralytics.com/assets/coco8.zip",
202
- path=Path.cwd(),
207
+ file_bytes: int,
208
+ path: str | Path = Path.cwd(),
203
209
  sf: float = 1.5,
204
210
  hard: bool = True,
205
211
  ) -> bool:
@@ -207,7 +213,7 @@ def check_disk_space(
207
213
  Check if there is sufficient disk space to download and store a file.
208
214
 
209
215
  Args:
210
- url (str, optional): The URL to the file.
216
+ file_bytes (int): The file size in bytes.
211
217
  path (str | Path, optional): The path or drive to check the available free space on.
212
218
  sf (float, optional): Safety factor, the multiplier for the required free space.
213
219
  hard (bool, optional): Whether to throw an error or not on insufficient disk space.
@@ -215,26 +221,14 @@ def check_disk_space(
215
221
  Returns:
216
222
  (bool): True if there is sufficient disk space, False otherwise.
217
223
  """
218
- import requests # slow import
219
-
220
- try:
221
- r = requests.head(url) # response
222
- assert r.status_code < 400, f"URL error for {url}: {r.status_code} {r.reason}" # check response
223
- except Exception:
224
- return True # requests issue, default to True
225
-
226
- # Check file size
227
- gib = 1 << 30 # bytes per GiB
228
- data = int(r.headers.get("Content-Length", 0)) / gib # file size (GB)
229
- total, used, free = (x / gib for x in shutil.disk_usage(path)) # bytes
230
-
231
- if data * sf < free:
224
+ total, used, free = shutil.disk_usage(path) # bytes
225
+ if file_bytes * sf < free:
232
226
  return True # sufficient space
233
227
 
234
228
  # Insufficient space
235
229
  text = (
236
- f"Insufficient free disk space {free:.1f} GB < {data * sf:.3f} GB required, "
237
- f"Please free {data * sf - free:.1f} GB additional disk space and try again."
230
+ f"Insufficient free disk space {free >> 30:.3f} GB < {int(file_bytes * sf) >> 30:.3f} GB required, "
231
+ f"Please free {int(file_bytes * sf - free) >> 30:.3f} GB additional disk space and try again."
238
232
  )
239
233
  if hard:
240
234
  raise MemoryError(text)
@@ -242,7 +236,7 @@ def check_disk_space(
242
236
  return False
243
237
 
244
238
 
245
- def get_google_drive_file_info(link: str) -> Tuple[str, str]:
239
+ def get_google_drive_file_info(link: str) -> tuple[str, str | None]:
246
240
  """
247
241
  Retrieve the direct download link and filename for a shareable Google Drive file link.
248
242
 
@@ -283,9 +277,9 @@ def get_google_drive_file_info(link: str) -> Tuple[str, str]:
283
277
 
284
278
 
285
279
  def safe_download(
286
- url,
287
- file=None,
288
- dir=None,
280
+ url: str | Path,
281
+ file: str | Path | None = None,
282
+ dir: str | Path | None = None,
289
283
  unzip: bool = True,
290
284
  delete: bool = False,
291
285
  curl: bool = False,
@@ -293,7 +287,7 @@ def safe_download(
293
287
  min_bytes: float = 1e0,
294
288
  exist_ok: bool = False,
295
289
  progress: bool = True,
296
- ):
290
+ ) -> Path | str:
297
291
  """
298
292
  Download files from a URL with options for retrying, unzipping, and deleting the downloaded file. Enhanced with
299
293
  robust partial download detection using Content-Length validation.
@@ -335,7 +329,6 @@ def safe_download(
335
329
  )
336
330
  desc = f"Downloading {uri} to '{f}'"
337
331
  f.parent.mkdir(parents=True, exist_ok=True) # make directory if missing
338
- check_disk_space(url, path=f.parent)
339
332
  curl_installed = shutil.which("curl")
340
333
  for i in range(retry + 1):
341
334
  try:
@@ -347,6 +340,9 @@ def safe_download(
347
340
  else: # urllib download
348
341
  with request.urlopen(url) as response:
349
342
  expected_size = int(response.getheader("Content-Length", 0))
343
+ if i == 0 and expected_size > 1048576:
344
+ check_disk_space(expected_size, path=f.parent)
345
+ buffer_size = max(8192, min(1048576, expected_size // 1000)) if expected_size else 8192
350
346
  with TQDM(
351
347
  total=expected_size,
352
348
  desc=desc,
@@ -356,7 +352,10 @@ def safe_download(
356
352
  unit_divisor=1024,
357
353
  ) as pbar:
358
354
  with open(f, "wb") as f_opened:
359
- for data in response:
355
+ while True:
356
+ data = response.read(buffer_size)
357
+ if not data:
358
+ break
360
359
  f_opened.write(data)
361
360
  pbar.update(len(data))
362
361
 
@@ -371,6 +370,8 @@ def safe_download(
371
370
  else:
372
371
  break # success
373
372
  f.unlink() # remove partial downloads
373
+ except MemoryError:
374
+ raise # Re-raise immediately - no point retrying if insufficient disk space
374
375
  except Exception as e:
375
376
  if i == 0 and not is_online():
376
377
  raise ConnectionError(emojis(f"❌ Download failure for {uri}. Environment is not online.")) from e
@@ -397,7 +398,7 @@ def get_github_assets(
397
398
  repo: str = "ultralytics/assets",
398
399
  version: str = "latest",
399
400
  retry: bool = False,
400
- ) -> Tuple[str, List[str]]:
401
+ ) -> tuple[str, list[str]]:
401
402
  """
402
403
  Retrieve the specified version's tag and assets from a GitHub repository.
403
404
 
@@ -430,7 +431,12 @@ def get_github_assets(
430
431
  return data["tag_name"], [x["name"] for x in data["assets"]] # tag, assets i.e. ['yolo11n.pt', 'yolov8s.pt', ...]
431
432
 
432
433
 
433
- def attempt_download_asset(file, repo: str = "ultralytics/assets", release: str = "v8.3.0", **kwargs) -> str:
434
+ def attempt_download_asset(
435
+ file: str | Path,
436
+ repo: str = "ultralytics/assets",
437
+ release: str = "v8.3.0",
438
+ **kwargs,
439
+ ) -> str:
434
440
  """
435
441
  Attempt to download a file from GitHub release assets if it is not found locally.
436
442
 
@@ -482,15 +488,15 @@ def attempt_download_asset(file, repo: str = "ultralytics/assets", release: str
482
488
 
483
489
 
484
490
  def download(
485
- url,
486
- dir=Path.cwd(),
491
+ url: str | list[str] | Path,
492
+ dir: Path = Path.cwd(),
487
493
  unzip: bool = True,
488
494
  delete: bool = False,
489
495
  curl: bool = False,
490
496
  threads: int = 1,
491
497
  retry: int = 3,
492
498
  exist_ok: bool = False,
493
- ):
499
+ ) -> None:
494
500
  """
495
501
  Download files from specified URLs to a given directory.
496
502
 
ultralytics/utils/tqdm.py CHANGED
@@ -10,7 +10,7 @@ from typing import IO, Any
10
10
 
11
11
 
12
12
  @lru_cache(maxsize=1)
13
- def is_noninteractive_console():
13
+ def is_noninteractive_console() -> bool:
14
14
  """Check for known non-interactive console environments."""
15
15
  return "GITHUB_ACTIONS" in os.environ or "RUNPOD_POD_ID" in os.environ
16
16
 
@@ -128,7 +128,7 @@ class TQDM:
128
128
 
129
129
  self.iterable = iterable
130
130
  self.desc = desc or ""
131
- self.total = total if total is not None else (len(iterable) if hasattr(iterable, "__len__") else None)
131
+ self.total = total or (len(iterable) if hasattr(iterable, "__len__") else None) or None # prevent total=0
132
132
  self.disable = disable
133
133
  self.unit = unit
134
134
  self.unit_scale = unit_scale
@@ -158,7 +158,7 @@ class TQDM:
158
158
  if not self.disable and self.total is not None and not self.noninteractive:
159
159
  self._display()
160
160
 
161
- def _format_rate(self, rate):
161
+ def _format_rate(self, rate: float) -> str:
162
162
  """Format rate with proper units and reasonable precision."""
163
163
  if rate <= 0:
164
164
  return ""
@@ -180,7 +180,7 @@ class TQDM:
180
180
  precision = ".1f" if rate >= 1 else ".2f"
181
181
  return f"{rate:{precision}}{self.unit}/s"
182
182
 
183
- def _format_num(self, num):
183
+ def _format_num(self, num: int) -> str:
184
184
  """Format number with optional unit scaling."""
185
185
  if not self.unit_scale or self.unit not in ("B", "bytes"):
186
186
  return str(num)
@@ -191,7 +191,7 @@ class TQDM:
191
191
  num /= self.unit_divisor
192
192
  return f"{num:.1f}PB"
193
193
 
194
- def _format_time(self, seconds):
194
+ def _format_time(self, seconds: float) -> str:
195
195
  """Format time duration."""
196
196
  if seconds < 60:
197
197
  return f"{seconds:.1f}s"
@@ -201,7 +201,7 @@ class TQDM:
201
201
  h, m = int(seconds // 3600), int((seconds % 3600) // 60)
202
202
  return f"{h}:{m:02d}:{seconds % 60:02.0f}"
203
203
 
204
- def _generate_bar(self, width=12):
204
+ def _generate_bar(self, width: int = 12) -> str:
205
205
  """Generate progress bar."""
206
206
  if self.total is None:
207
207
  return "━" * width if self.closed else "─" * width
@@ -213,7 +213,7 @@ class TQDM:
213
213
  bar = bar[:filled] + "╸" + bar[filled + 1 :]
214
214
  return bar
215
215
 
216
- def _should_update(self, dt, dn):
216
+ def _should_update(self, dt: float, dn: int) -> bool:
217
217
  """Check if display should update."""
218
218
  if self.noninteractive:
219
219
  return False
@@ -223,7 +223,7 @@ class TQDM:
223
223
 
224
224
  return dt >= self.mininterval
225
225
 
226
- def _display(self, final=False):
226
+ def _display(self, final: bool = False) -> None:
227
227
  """Display progress bar."""
228
228
  if self.disable or (self.closed and not final):
229
229
  return
@@ -296,26 +296,26 @@ class TQDM:
296
296
  except Exception:
297
297
  pass
298
298
 
299
- def update(self, n=1):
299
+ def update(self, n: int = 1) -> None:
300
300
  """Update progress by n steps."""
301
301
  if not self.disable and not self.closed:
302
302
  self.n += n
303
303
  self._display()
304
304
 
305
- def set_description(self, desc):
305
+ def set_description(self, desc: str | None) -> None:
306
306
  """Set description."""
307
307
  self.desc = desc or ""
308
308
  if not self.disable:
309
309
  self._display()
310
310
 
311
- def set_postfix(self, **kwargs):
311
+ def set_postfix(self, **kwargs: Any) -> None:
312
312
  """Set postfix (appends to description)."""
313
313
  if kwargs:
314
314
  postfix = ", ".join(f"{k}={v}" for k, v in kwargs.items())
315
315
  base_desc = self.desc.split(" | ")[0] if " | " in self.desc else self.desc
316
316
  self.set_description(f"{base_desc} | {postfix}")
317
317
 
318
- def close(self):
318
+ def close(self) -> None:
319
319
  """Close progress bar."""
320
320
  if self.closed:
321
321
  return
@@ -339,15 +339,15 @@ class TQDM:
339
339
  except Exception:
340
340
  pass
341
341
 
342
- def __enter__(self):
342
+ def __enter__(self) -> TQDM:
343
343
  """Enter context manager."""
344
344
  return self
345
345
 
346
- def __exit__(self, *args):
346
+ def __exit__(self, *args: Any) -> None:
347
347
  """Exit context manager and close progress bar."""
348
348
  self.close()
349
349
 
350
- def __iter__(self):
350
+ def __iter__(self) -> Any:
351
351
  """Iterate over the wrapped iterable with progress updates."""
352
352
  if self.iterable is None:
353
353
  raise TypeError("'NoneType' object is not iterable")
@@ -359,19 +359,19 @@ class TQDM:
359
359
  finally:
360
360
  self.close()
361
361
 
362
- def __del__(self):
362
+ def __del__(self) -> None:
363
363
  """Destructor to ensure cleanup."""
364
364
  try:
365
365
  self.close()
366
366
  except Exception:
367
367
  pass
368
368
 
369
- def refresh(self):
369
+ def refresh(self) -> None:
370
370
  """Refresh display."""
371
371
  if not self.disable:
372
372
  self._display()
373
373
 
374
- def clear(self):
374
+ def clear(self) -> None:
375
375
  """Clear progress bar."""
376
376
  if not self.disable:
377
377
  try:
@@ -381,7 +381,7 @@ class TQDM:
381
381
  pass
382
382
 
383
383
  @staticmethod
384
- def write(s, file=None, end="\n"):
384
+ def write(s: str, file: IO[str] | None = None, end: str = "\n") -> None:
385
385
  """Static method to write without breaking progress bar."""
386
386
  file = file or sys.stdout
387
387
  try:
@@ -394,14 +394,11 @@ class TQDM:
394
394
  if __name__ == "__main__":
395
395
  import time
396
396
 
397
- # Example 1: Basic usage with known total
398
397
  print("1. Basic progress bar with known total:")
399
- for i in TQDM(range(20), desc="Known total"):
398
+ for i in TQDM(range(0), desc="Known total"):
400
399
  time.sleep(0.05)
401
- print()
402
400
 
403
- # Example 2: Manual updates with known total
404
- print("2. Manual updates with known total:")
401
+ print("\n2. Manual updates with known total:")
405
402
  pbar = TQDM(total=30, desc="Manual updates", unit="files")
406
403
  for i in range(30):
407
404
  time.sleep(0.03)
@@ -409,10 +406,8 @@ if __name__ == "__main__":
409
406
  if i % 10 == 9:
410
407
  pbar.set_description(f"Processing batch {i // 10 + 1}")
411
408
  pbar.close()
412
- print()
413
409
 
414
- # Example 3: Unknown total - this was the problematic case
415
- print("3. Progress bar with unknown total:")
410
+ print("\n3. Progress bar with unknown total:")
416
411
  pbar = TQDM(desc="Unknown total", unit="items")
417
412
  for i in range(25):
418
413
  time.sleep(0.08)
@@ -420,18 +415,14 @@ if __name__ == "__main__":
420
415
  if i % 5 == 4:
421
416
  pbar.set_postfix(processed=i + 1, status="OK")
422
417
  pbar.close()
423
- print()
424
418
 
425
- # Example 4: Context manager with unknown total
426
- print("4. Context manager with unknown total:")
419
+ print("\n4. Context manager with unknown total:")
427
420
  with TQDM(desc="Processing stream", unit="B", unit_scale=True, unit_divisor=1024) as pbar:
428
421
  for i in range(30):
429
422
  time.sleep(0.1)
430
423
  pbar.update(1024 * 1024 * i) # Simulate processing MB of data
431
- print()
432
424
 
433
- # Example 5: Generator with unknown length
434
- print("5. Iterator with unknown length:")
425
+ print("\n5. Iterator with unknown length:")
435
426
 
436
427
  def data_stream():
437
428
  """Simulate a data stream of unknown length."""
@@ -442,10 +433,8 @@ if __name__ == "__main__":
442
433
 
443
434
  for chunk in TQDM(data_stream(), desc="Stream processing", unit="chunks"):
444
435
  time.sleep(0.1)
445
- print()
446
436
 
447
- # Example 6: File-like processing simulation
448
- print("6. File processing simulation (unknown size):")
437
+ print("\n6. File processing simulation (unknown size):")
449
438
 
450
439
  def process_files():
451
440
  """Simulate processing files of unknown count."""
@@ -459,4 +448,3 @@ if __name__ == "__main__":
459
448
  pbar.update(1)
460
449
  pbar.set_description(f"Processing {filename}")
461
450
  pbar.close()
462
- print()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ultralytics
3
- Version: 8.3.187
3
+ Version: 8.3.188
4
4
  Summary: Ultralytics YOLO 🚀 for SOTA object detection, multi-object tracking, instance segmentation, pose estimation and image classification.
5
5
  Author-email: Glenn Jocher <glenn.jocher@ultralytics.com>, Jing Qiu <jing.qiu@ultralytics.com>
6
6
  Maintainer-email: Ultralytics <hello@ultralytics.com>
@@ -58,7 +58,8 @@ Requires-Dist: mkdocs-ultralytics-plugin>=0.1.29; extra == "dev"
58
58
  Requires-Dist: mkdocs-macros-plugin>=1.0.5; extra == "dev"
59
59
  Provides-Extra: export
60
60
  Requires-Dist: numpy<2.0.0; extra == "export"
61
- Requires-Dist: onnx<1.18.0,>=1.12.0; extra == "export"
61
+ Requires-Dist: onnx>=1.12.0; platform_system != "Darwin" and extra == "export"
62
+ Requires-Dist: onnx<1.18.0,>=1.12.0; platform_system == "Darwin" and extra == "export"
62
63
  Requires-Dist: coremltools>=8.0; (platform_system != "Windows" and python_version <= "3.13") and extra == "export"
63
64
  Requires-Dist: scikit-learn>=1.3.2; (platform_system != "Windows" and python_version <= "3.13") and extra == "export"
64
65
  Requires-Dist: openvino>=2024.0.0; extra == "export"
@@ -7,7 +7,7 @@ tests/test_exports.py,sha256=CY-4xVZlVM16vdyIC0mSR3Ix59aiZm1qjFGIhSNmB20,11007
7
7
  tests/test_integrations.py,sha256=kl_AKmE_Qs1GB0_91iVwbzNxofm_hFTt0zzU6JF-pg4,6323
8
8
  tests/test_python.py,sha256=ENUbLIobqCZAxEy9W7gvhmkmW5OJ2oG-3gI8QLiJjzs,28020
9
9
  tests/test_solutions.py,sha256=tuf6n_fsI8KvSdJrnc-cqP2qYdiYqCWuVrx0z9dOz3Q,13213
10
- ultralytics/__init__.py,sha256=AOe0V1kT_XRgsl4BfS_o9VX8oL3rLcEYJgfpuMGLG2A,730
10
+ ultralytics/__init__.py,sha256=VYZePcNS8EQcTsoJ-lwabUjlQSP3Owuwsy4J8LCbNsQ,730
11
11
  ultralytics/py.typed,sha256=la67KBlbjXN-_-DfGNcdOcjYumVpKG_Tkw-8n5dnGB4,8
12
12
  ultralytics/assets/bus.jpg,sha256=wCAZxJecGR63Od3ZRERe9Aja1Weayrb9Ug751DS_vGM,137419
13
13
  ultralytics/assets/zidane.jpg,sha256=Ftc4aeMmen1O0A3o6GCDO9FlfBslLpTAw0gnetx7bts,50427
@@ -120,7 +120,7 @@ ultralytics/data/scripts/get_coco.sh,sha256=UuJpJeo3qQpTHVINeOpmP0NYmg8PhEFE3A8J
120
120
  ultralytics/data/scripts/get_coco128.sh,sha256=qmRQl_hOKrsdHrTrnyQuFIH01oDz3lfaz138OgGfLt8,650
121
121
  ultralytics/data/scripts/get_imagenet.sh,sha256=hr42H16bM47iT27rgS7MpEo-GeOZAYUQXgr0B2cwn48,1705
122
122
  ultralytics/engine/__init__.py,sha256=lm6MckFYCPTbqIoX7w0s_daxdjNeBeKW6DXppv1-QUM,70
123
- ultralytics/engine/exporter.py,sha256=-AUku73LwK0l_Gt71evXQIJg3WpC2jr73S-87vw5T6g,75277
123
+ ultralytics/engine/exporter.py,sha256=qHGD5wFmka_o8BNZTiPH8Qfp7-_y7Cz-OREOsfw9vmM,75261
124
124
  ultralytics/engine/model.py,sha256=877u2n0ISz2COOYtEMUqQe0E-HHB4Atb2DuH1XCE98k,53530
125
125
  ultralytics/engine/predictor.py,sha256=iXnUB-tvBHtVpKbB-5EKs1wSREBIerdUxWx39MaFYuk,22485
126
126
  ultralytics/engine/results.py,sha256=6xagidv6FDJlstAX6tHob_mgfNs3459JVWeyOZgNpko,71686
@@ -146,7 +146,7 @@ ultralytics/models/rtdetr/__init__.py,sha256=_jEHmOjI_QP_nT3XJXLgYHQ6bXG4EL8Gnvn
146
146
  ultralytics/models/rtdetr/model.py,sha256=e2u6kQEYawRXGGO6HbFDE1uyHfsIqvKk4IpVjjYN41k,2182
147
147
  ultralytics/models/rtdetr/predict.py,sha256=Jqorq8OkGgXCCRS8DmeuGQj3XJxEhz97m22p7VxzXTw,4279
148
148
  ultralytics/models/rtdetr/train.py,sha256=6FA3nDEcH1diFQ8Ky0xENp9cOOYATHxU6f42z9npMvs,3766
149
- ultralytics/models/rtdetr/val.py,sha256=QT7JNKFJmD8dqUVSUBb78t9wGtE7KEw5l92CKJU50TM,8849
149
+ ultralytics/models/rtdetr/val.py,sha256=8WVwlfSa6V8PQdFJIFp2bmKTZ_kBoLEvnXMLf08BbWI,8913
150
150
  ultralytics/models/sam/__init__.py,sha256=4VtjxrbrSsqBvteaD_CwA4Nj3DdSUG1MknymtWwRMbc,359
151
151
  ultralytics/models/sam/amg.py,sha256=IpcuIfC5KBRiF4sdrsPl1ecWEJy75axo1yG23r5BFsw,11783
152
152
  ultralytics/models/sam/build.py,sha256=J6n-_QOYLa63jldEZmhRe9D3Is_AJE8xyZLUjzfRyTY,12629
@@ -173,11 +173,11 @@ ultralytics/models/yolo/classify/val.py,sha256=iQZRS6D3-YQjygBhFpC8VCJMI05L3uUPe
173
173
  ultralytics/models/yolo/detect/__init__.py,sha256=GIRsLYR-kT4JJx7lh4ZZAFGBZj0aebokuU0A7JbjDVA,257
174
174
  ultralytics/models/yolo/detect/predict.py,sha256=ySUsdIf8dw00bzWhcxN1jZwLWKPRT2M7-N7TNL3o4zo,5387
175
175
  ultralytics/models/yolo/detect/train.py,sha256=HlaCoHJ6Y2TpCXXWabMRZApAYqBvjuM_YQJUV5JYCvw,9907
176
- ultralytics/models/yolo/detect/val.py,sha256=q_kpP3eyVQ5zTkqQ-kc5JhWaKGrtIdN076bMtB6wc2g,20968
176
+ ultralytics/models/yolo/detect/val.py,sha256=rHg0lPC0ccGbVF6113-18grCViVgGdXkg-aT-0sWT4U,21318
177
177
  ultralytics/models/yolo/obb/__init__.py,sha256=tQmpG8wVHsajWkZdmD6cjGohJ4ki64iSXQT8JY_dydo,221
178
178
  ultralytics/models/yolo/obb/predict.py,sha256=4r1eSld6TNJlk9JG56e-DX6oPL8uBBqiuztyBpxWlHE,2888
179
179
  ultralytics/models/yolo/obb/train.py,sha256=bnYFAMur7Uvbw5Dc09-S2ge7B05iGX-t37Ksgc0ef6g,3921
180
- ultralytics/models/yolo/obb/val.py,sha256=pSHQZ6YedCqryYbOiNtVCWZRFeKYa8EJzAGA2Heu3r0,14021
180
+ ultralytics/models/yolo/obb/val.py,sha256=I05mwGK620JFBz9yuGPlV9NN1fsWZE0lDqMxL5iG9YA,14085
181
181
  ultralytics/models/yolo/pose/__init__.py,sha256=63xmuHZLNzV8I76HhVXAq4f2W0KTk8Oi9eL-Y204LyQ,227
182
182
  ultralytics/models/yolo/pose/predict.py,sha256=M0C7ZfVXx4QXgv-szjnaXYEPas76ZLGAgDNNh1GG0vI,3743
183
183
  ultralytics/models/yolo/pose/train.py,sha256=GyvNnDPJ3UFq_90HN8_FJ0dbwRkw3JJTVpkMFH0vC0o,5457
@@ -185,7 +185,7 @@ ultralytics/models/yolo/pose/val.py,sha256=4aOTgor8EcWvLEN5wCbk9I7ILFvb1q8_F1LlH
185
185
  ultralytics/models/yolo/segment/__init__.py,sha256=3IThhZ1wlkY9FvmWm9cE-5-ZyE6F1FgzAtQ6jOOFzzw,275
186
186
  ultralytics/models/yolo/segment/predict.py,sha256=qlprQCZn4_bpjpI08U0MU9Q9_1gpHrw_7MXwtXE1l1Y,5377
187
187
  ultralytics/models/yolo/segment/train.py,sha256=XrPkXUiNu1Jvhn8iDew_RaLLjZA3un65rK-QH9mtNIw,3802
188
- ultralytics/models/yolo/segment/val.py,sha256=w0Lvx0JOqj1oHJxmlVhDqYUxZS9yxzLWocOixwNxnKo,11447
188
+ ultralytics/models/yolo/segment/val.py,sha256=GRlHSN75j7M3B5rP5owop5LzG7THIzzCxhNgec3Qi1c,11309
189
189
  ultralytics/models/yolo/world/__init__.py,sha256=nlh8I6t8hMGz_vZg8QSlsUW1R-2eKvn9CGUoPPQEGhA,131
190
190
  ultralytics/models/yolo/world/train.py,sha256=wBKnSC-TvrKWM1Taxqwo13XcwGHwwAXzNYV1tmqcOpc,7845
191
191
  ultralytics/models/yolo/world/train_world.py,sha256=lk9z_INGPSTP_W7Rjh3qrWSmjHaxOJtGngonh1cj2SM,9551
@@ -238,10 +238,10 @@ ultralytics/trackers/utils/matching.py,sha256=uSYtywqi1lE_uNN1FwuBFPyISfDQXHMu8K
238
238
  ultralytics/utils/__init__.py,sha256=ONuTxJMXtc5k7hR9FFhD5c530gmJpeBpCJeJVhdLUP8,53936
239
239
  ultralytics/utils/autobatch.py,sha256=33m8YgggLIhltDqMXZ5OE-FGs2QiHrl2-LfgY1mI4cw,5119
240
240
  ultralytics/utils/autodevice.py,sha256=1wwjkO2tmyR5IAYa6t8G9QJgGrm00niPY4bTbTRH0Uk,8861
241
- ultralytics/utils/benchmarks.py,sha256=wYO6iuF26aG_BqBmdAusZdQRmSHcvMK4i-S0x7Q6ugw,31090
241
+ ultralytics/utils/benchmarks.py,sha256=wqIdUpYLp3Ac-oWX9bgngqOvmGyUiKuI61KBOcCqR6A,31479
242
242
  ultralytics/utils/checks.py,sha256=q64U5wKyejD-2W2fCPqJ0Oiaa4_4vq2pVxV9wp6lMz4,34707
243
243
  ultralytics/utils/dist.py,sha256=A9lDGtGefTjSVvVS38w86GOdbtLzNBDZuDGK0MT4PRI,4170
244
- ultralytics/utils/downloads.py,sha256=5p9X5XN3I4RzZYGv8wP8Iehm3fDR4KXtN7KgGsJ0iAg,22621
244
+ ultralytics/utils/downloads.py,sha256=jtaStUmZiWhJ9-ovubsSJHqnWS891qIZggQHGUC0fJo,23009
245
245
  ultralytics/utils/errors.py,sha256=XT9Ru7ivoBgofK6PlnyigGoa7Fmf5nEhyHtnD-8TRXI,1584
246
246
  ultralytics/utils/export.py,sha256=LK-wlTlyb_zIKtSvOmfmvR70RcUU9Ct9UBDt5wn9_rY,9880
247
247
  ultralytics/utils/files.py,sha256=ZCbLGleiF0f-PqYfaxMFAWop88w7U1hpreHXl8b2ko0,8238
@@ -254,7 +254,7 @@ ultralytics/utils/patches.py,sha256=PPWiKzwGbCvuawLzDKVR8tWOQAlZbJBi8g_-A6eTCYA,
254
254
  ultralytics/utils/plotting.py,sha256=npFWWIGEdQM3IsSSqoZ29kAFyCN3myeZOFj-gALFT6M,47465
255
255
  ultralytics/utils/tal.py,sha256=aXawOnhn8ni65tJWIW-PYqWr_TRvltbHBjrTo7o6lDQ,20924
256
256
  ultralytics/utils/torch_utils.py,sha256=D76Pvmw5OKh-vd4aJkOMO0dSLbM5WzGr7Hmds54hPEk,39233
257
- ultralytics/utils/tqdm.py,sha256=cJSzlv6NP72kN7_J0PETA3h4bwGh5a_YHA2gdmZqL8U,16535
257
+ ultralytics/utils/tqdm.py,sha256=G7V-0Ku_XEKKjA8D2duWD9OToekX2LGLbbOTzd1UrWo,16414
258
258
  ultralytics/utils/triton.py,sha256=M7qe4RztiADBJQEWQKaIQsp94ERFJ_8_DUHDR6TXEOM,5410
259
259
  ultralytics/utils/tuner.py,sha256=bHr09Fz-0-t0ei55gX5wJh-obyiAQoicP7HUVM2I8qA,6826
260
260
  ultralytics/utils/callbacks/__init__.py,sha256=hzL63Rce6VkZhP4Lcim9LKjadixaQG86nKqPhk7IkS0,242
@@ -269,9 +269,9 @@ ultralytics/utils/callbacks/platform.py,sha256=gdbEuedXEs1VjdU0IiedjPFwttZJUiI0d
269
269
  ultralytics/utils/callbacks/raytune.py,sha256=S6Bq16oQDQ8BQgnZzA0zJHGN_BBr8iAM_WtGoLiEcwg,1283
270
270
  ultralytics/utils/callbacks/tensorboard.py,sha256=MDPBW7aDes-66OE6YqKXXvqA_EocjzEMHWGM-8z9vUQ,5281
271
271
  ultralytics/utils/callbacks/wb.py,sha256=ngQO8EJ1kxJDF1YajScVtzBbm26jGuejA0uWeOyvf5A,7685
272
- ultralytics-8.3.187.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
273
- ultralytics-8.3.187.dist-info/METADATA,sha256=TFxzkVKluL536eSw5JErgR_J1Fl82oS5vEAKrElKYo8,37582
274
- ultralytics-8.3.187.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
275
- ultralytics-8.3.187.dist-info/entry_points.txt,sha256=YM_wiKyTe9yRrsEfqvYolNO5ngwfoL4-NwgKzc8_7sI,93
276
- ultralytics-8.3.187.dist-info/top_level.txt,sha256=XP49TwiMw4QGsvTLSYiJhz1xF_k7ev5mQ8jJXaXi45Q,12
277
- ultralytics-8.3.187.dist-info/RECORD,,
272
+ ultralytics-8.3.188.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
273
+ ultralytics-8.3.188.dist-info/METADATA,sha256=X4WwCg6NM20Jl6Kd_3qiOyrfmUSOaYEonERNeBDscS4,37693
274
+ ultralytics-8.3.188.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
275
+ ultralytics-8.3.188.dist-info/entry_points.txt,sha256=YM_wiKyTe9yRrsEfqvYolNO5ngwfoL4-NwgKzc8_7sI,93
276
+ ultralytics-8.3.188.dist-info/top_level.txt,sha256=XP49TwiMw4QGsvTLSYiJhz1xF_k7ev5mQ8jJXaXi45Q,12
277
+ ultralytics-8.3.188.dist-info/RECORD,,