ultralytics 8.3.135__py3-none-any.whl → 8.3.136__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.135"
3
+ __version__ = "8.3.136"
4
4
 
5
5
  import os
6
6
 
@@ -7,8 +7,6 @@ from pathlib import Path
7
7
  from types import SimpleNamespace
8
8
  from typing import Any, Dict, List, Union
9
9
 
10
- import cv2
11
-
12
10
  from ultralytics import __version__
13
11
  from ultralytics.utils import (
14
12
  ASSETS,
@@ -707,6 +705,8 @@ def handle_yolo_solutions(args: List[str]) -> None:
707
705
  ]
708
706
  )
709
707
  else:
708
+ import cv2 # Only needed for cap and vw functionality
709
+
710
710
  from ultralytics import solutions
711
711
 
712
712
  solution = getattr(solutions, SOLUTION_MAP[solution_name])(is_cli=True, **overrides) # class i.e ObjectCounter
@@ -919,7 +919,7 @@ def entrypoint(debug: str = "") -> None:
919
919
  if task not in TASKS:
920
920
  if task == "track":
921
921
  LOGGER.warning(
922
- "invalid 'task=track', setting 'task=detect' and 'mode=track'. Valid tasks are {TASKS}.\n{CLI_HELP_MSG}."
922
+ f"invalid 'task=track', setting 'task=detect' and 'mode=track'. Valid tasks are {TASKS}.\n{CLI_HELP_MSG}."
923
923
  )
924
924
  task, mode = "detect", "track"
925
925
  else:
@@ -80,6 +80,7 @@ def parse_requirements(file_path=ROOT.parent / "requirements.txt", package=""):
80
80
  return requirements
81
81
 
82
82
 
83
+ @functools.lru_cache
83
84
  def parse_version(version="0.0.0") -> tuple:
84
85
  """
85
86
  Convert a version string to a tuple of integers, ignoring any extra non-numeric string attached to the version.
@@ -164,6 +165,7 @@ def check_imgsz(imgsz, stride=32, min_dim=1, max_dim=2, floor=0):
164
165
  return sz
165
166
 
166
167
 
168
+ @functools.lru_cache
167
169
  def check_version(
168
170
  current: str = "0.0.0",
169
171
  required: str = "0.0.0",
@@ -580,6 +582,7 @@ def check_is_path_safe(basedir, path):
580
582
  return path_resolved.exists() and path_resolved.parts[: len(base_dir_resolved.parts)] == base_dir_resolved.parts
581
583
 
582
584
 
585
+ @functools.lru_cache
583
586
  def check_imshow(warn=False):
584
587
  """
585
588
  Check if environment supports image displays.
@@ -409,7 +409,7 @@ class ConfusionMatrix:
409
409
  @plt_settings()
410
410
  def plot(self, normalize=True, save_dir="", names=(), on_plot=None):
411
411
  """
412
- Plot the confusion matrix using seaborn and save it to a file.
412
+ Plot the confusion matrix using matplotlib and save it to a file.
413
413
 
414
414
  Args:
415
415
  normalize (bool): Whether to normalize the confusion matrix.
@@ -418,34 +418,63 @@ class ConfusionMatrix:
418
418
  on_plot (func): An optional callback to pass plots path and data when they are rendered.
419
419
  """
420
420
  import matplotlib.pyplot as plt # scope for faster 'import ultralytics'
421
- import seaborn
422
421
 
423
422
  array = self.matrix / ((self.matrix.sum(0).reshape(1, -1) + 1e-9) if normalize else 1) # normalize columns
424
423
  array[array < 0.005] = np.nan # don't annotate (would appear as 0.00)
425
424
 
426
- fig, ax = plt.subplots(1, 1, figsize=(12, 9), tight_layout=True)
427
- nc, nn = self.nc, len(names) # number of classes, names
428
- seaborn.set_theme(font_scale=1.0 if nc < 50 else 0.8) # for label size
429
- labels = (0 < nn < 99) and (nn == nc) # apply names to ticklabels
430
- ticklabels = (list(names) + ["background"]) if labels else "auto"
425
+ names = list(names)
426
+ fig, ax = plt.subplots(1, 1, figsize=(12, 9))
427
+ if self.nc >= 100: # downsample for large class count
428
+ k = max(2, self.nc // 60) # step size for downsampling, always > 1
429
+ keep_idx = slice(None, None, k) # create slice instead of array
430
+ names = names[keep_idx] # slice class names
431
+ array = array[keep_idx, :][:, keep_idx] # slice matrix rows and cols
432
+ n = (self.nc + k - 1) // k # number of retained classes
433
+ nc = nn = n if self.task == "classify" else n + 1 # adjust for background if needed
434
+ else:
435
+ nc = nn = self.nc if self.task == "classify" else self.nc + 1
436
+ ticklabels = (names + ["background"]) if (0 < nn < 99) and (nn == nc) else "auto"
437
+ xy_ticks = np.arange(len(ticklabels))
438
+ tick_fontsize = max(6, 15 - 0.1 * nc) # Minimum size is 6
439
+ label_fontsize = max(6, 12 - 0.1 * nc)
440
+ title_fontsize = max(6, 12 - 0.1 * nc)
441
+ btm = max(0.1, 0.25 - 0.001 * nc) # Minimum value is 0.1
431
442
  with warnings.catch_warnings():
432
443
  warnings.simplefilter("ignore") # suppress empty matrix RuntimeWarning: All-NaN slice encountered
433
- seaborn.heatmap(
434
- array,
435
- ax=ax,
436
- annot=nc < 30,
437
- annot_kws={"size": 8},
438
- cmap="Blues",
439
- fmt=".2f" if normalize else ".0f",
440
- square=True,
441
- vmin=0.0,
442
- xticklabels=ticklabels,
443
- yticklabels=ticklabels,
444
- ).set_facecolor((1, 1, 1))
444
+ im = ax.imshow(array, cmap="Blues", vmin=0.0, interpolation="none")
445
+ ax.xaxis.set_label_position("bottom")
446
+ if nc < 30: # Add score for each cell of confusion matrix
447
+ for i, row in enumerate(array[:nc]):
448
+ for j, val in enumerate(row[:nc]):
449
+ val = array[i, j]
450
+ if np.isnan(val):
451
+ continue
452
+ ax.text(
453
+ j,
454
+ i,
455
+ f"{val:.2f}" if normalize else f"{int(val)}",
456
+ ha="center",
457
+ va="center",
458
+ fontsize=10,
459
+ color="white" if val > (0.7 if normalize else 2) else "black",
460
+ )
461
+ cbar = fig.colorbar(im, ax=ax, fraction=0.046, pad=0.05)
445
462
  title = "Confusion Matrix" + " Normalized" * normalize
446
- ax.set_xlabel("True")
447
- ax.set_ylabel("Predicted")
448
- ax.set_title(title)
463
+ ax.set_xlabel("True", fontsize=label_fontsize, labelpad=10)
464
+ ax.set_ylabel("Predicted", fontsize=label_fontsize, labelpad=10)
465
+ ax.set_title(title, fontsize=title_fontsize, pad=20)
466
+ ax.set_xticks(xy_ticks)
467
+ ax.set_yticks(xy_ticks)
468
+ ax.tick_params(axis="x", bottom=True, top=False, labelbottom=True, labeltop=False)
469
+ ax.tick_params(axis="y", left=True, right=False, labelleft=True, labelright=False)
470
+ if ticklabels != "auto":
471
+ ax.set_xticklabels(ticklabels, fontsize=tick_fontsize, rotation=90, ha="center")
472
+ ax.set_yticklabels(ticklabels, fontsize=tick_fontsize)
473
+ for s in ["left", "right", "bottom", "top", "outline"]:
474
+ if s != "outline":
475
+ ax.spines[s].set_visible(False) # Confusion matrix plot don't have outline
476
+ cbar.ax.spines[s].set_visible(False)
477
+ fig.subplots_adjust(left=0, right=0.84, top=0.94, bottom=btm) # Adjust layout to ensure equal margins
449
478
  plot_fname = Path(save_dir) / f"{title.lower().replace(' ', '_')}.png"
450
479
  fig.savefig(plot_fname, dpi=250)
451
480
  plt.close(fig)
@@ -537,9 +537,9 @@ def plot_labels(boxes, cls, names=(), save_dir=Path(""), on_plot=None):
537
537
  """
538
538
  import matplotlib.pyplot as plt # scope for faster 'import ultralytics'
539
539
  import pandas
540
- import seaborn
540
+ from matplotlib.colors import LinearSegmentedColormap
541
541
 
542
- # Filter matplotlib>=3.7.2 warning and Seaborn use_inf and is_categorical FutureWarnings
542
+ # Filter matplotlib>=3.7.2 warning
543
543
  warnings.filterwarnings("ignore", category=UserWarning, message="The figure layout has changed to tight")
544
544
  warnings.filterwarnings("ignore", category=FutureWarning)
545
545
 
@@ -549,12 +549,17 @@ def plot_labels(boxes, cls, names=(), save_dir=Path(""), on_plot=None):
549
549
  boxes = boxes[:1000000] # limit to 1M boxes
550
550
  x = pandas.DataFrame(boxes, columns=["x", "y", "width", "height"])
551
551
 
552
- # Seaborn correlogram
553
- seaborn.pairplot(x, corner=True, diag_kind="auto", kind="hist", diag_kws=dict(bins=50), plot_kws=dict(pmax=0.9))
554
- plt.savefig(save_dir / "labels_correlogram.jpg", dpi=200)
555
- plt.close()
552
+ try: # Seaborn correlogram
553
+ import seaborn
554
+
555
+ seaborn.pairplot(x, corner=True, diag_kind="auto", kind="hist", diag_kws=dict(bins=50), plot_kws=dict(pmax=0.9))
556
+ plt.savefig(save_dir / "labels_correlogram.jpg", dpi=200)
557
+ plt.close()
558
+ except ImportError:
559
+ pass # Skip if seaborn is not installed
556
560
 
557
561
  # Matplotlib labels
562
+ subplot_3_4_color = LinearSegmentedColormap.from_list("white_blue", ["white", "blue"])
558
563
  ax = plt.subplots(2, 2, figsize=(8, 8), tight_layout=True)[1].ravel()
559
564
  y = ax[0].hist(cls, bins=np.linspace(0, nc, nc + 1) - 0.5, rwidth=0.8)
560
565
  for i in range(nc):
@@ -565,18 +570,19 @@ def plot_labels(boxes, cls, names=(), save_dir=Path(""), on_plot=None):
565
570
  ax[0].set_xticklabels(list(names.values()), rotation=90, fontsize=10)
566
571
  else:
567
572
  ax[0].set_xlabel("classes")
568
- seaborn.histplot(x, x="x", y="y", ax=ax[2], bins=50, pmax=0.9)
569
- seaborn.histplot(x, x="width", y="height", ax=ax[3], bins=50, pmax=0.9)
570
-
571
- # Rectangles
572
- boxes[:, 0:2] = 0.5 # center
573
- boxes = ops.xywh2xyxy(boxes) * 1000
573
+ boxes = np.column_stack([0.5 - boxes[:, 2:4] / 2, 0.5 + boxes[:, 2:4] / 2]) * 1000
574
574
  img = Image.fromarray(np.ones((1000, 1000, 3), dtype=np.uint8) * 255)
575
575
  for cls, box in zip(cls[:500], boxes[:500]):
576
576
  ImageDraw.Draw(img).rectangle(box, width=1, outline=colors(cls)) # plot
577
577
  ax[1].imshow(img)
578
578
  ax[1].axis("off")
579
579
 
580
+ ax[2].hist2d(x["x"], x["y"], bins=50, cmap=subplot_3_4_color)
581
+ ax[2].set_xlabel("x")
582
+ ax[2].set_ylabel("y")
583
+ ax[3].hist2d(x["width"], x["height"], bins=50, cmap=subplot_3_4_color)
584
+ ax[3].set_xlabel("width")
585
+ ax[3].set_ylabel("height")
580
586
  for a in [0, 1, 2, 3]:
581
587
  for s in ["top", "right", "left", "bottom"]:
582
588
  ax[a].spines[s].set_visible(False)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ultralytics
3
- Version: 8.3.135
3
+ Version: 8.3.136
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>
@@ -46,7 +46,6 @@ Requires-Dist: tqdm>=4.64.0
46
46
  Requires-Dist: psutil
47
47
  Requires-Dist: py-cpuinfo
48
48
  Requires-Dist: pandas>=1.1.4
49
- Requires-Dist: seaborn>=0.11.0
50
49
  Requires-Dist: ultralytics-thop>=2.0.0
51
50
  Provides-Extra: dev
52
51
  Requires-Dist: ipython; extra == "dev"
@@ -7,10 +7,10 @@ tests/test_exports.py,sha256=UeeBloqYYGZNh520R3CR80XBxA9XFrNmbK9An6V6C4w,9838
7
7
  tests/test_integrations.py,sha256=dQteeRsRVuT_p5-T88-7jqT65Zm9iAXkyKg-KQ1_TQ8,6341
8
8
  tests/test_python.py,sha256=KWsncKpeDdRmjRftmJpsMl7bBLI3TG_I7Lb4kuemZzQ,25618
9
9
  tests/test_solutions.py,sha256=IFlqyOUCvGbLe_YZqWmNCe_afg4as0p-SfAv3j7VURI,6205
10
- ultralytics/__init__.py,sha256=7IMXy8Z7sekeQRLOVZyuYbA-1kse0gieArFyUxQ9dyE,730
10
+ ultralytics/__init__.py,sha256=eHclh3QJTVw22eqcJwLs0T_o2qu2cint1eUqK2QuSJs,730
11
11
  ultralytics/assets/bus.jpg,sha256=wCAZxJecGR63Od3ZRERe9Aja1Weayrb9Ug751DS_vGM,137419
12
12
  ultralytics/assets/zidane.jpg,sha256=Ftc4aeMmen1O0A3o6GCDO9FlfBslLpTAw0gnetx7bts,50427
13
- ultralytics/cfg/__init__.py,sha256=p1dKUDoVsnjJG8Qj5Q-eukb0WH2IoWV3BcJpEmKu2tE,39487
13
+ ultralytics/cfg/__init__.py,sha256=h0UVCvX6DIpoR4_pthpZD_Ihq7eCaS8HbXsPOm82G0E,39540
14
14
  ultralytics/cfg/default.yaml,sha256=oFG6llJO-Py5H-cR9qs-7FieJamroDLwpbrkhmfROOM,8307
15
15
  ultralytics/cfg/datasets/Argoverse.yaml,sha256=_xlEDIJ9XkUo0v_iNL7FW079BoSeZtKSuLteKTtGbA8,3275
16
16
  ultralytics/cfg/datasets/DOTAv1.5.yaml,sha256=SHND_CFkojxw5iQD5Mcgju2kCZIl0gW2ajuzv1cqoL0,1224
@@ -237,7 +237,7 @@ ultralytics/utils/__init__.py,sha256=vac0M-Hx55QXl6Vod3QPjnLBlt87Hwxu1784RXPmeQA
237
237
  ultralytics/utils/autobatch.py,sha256=kg05q2qKg74y_Uq2vvr01i3KhLfpVR7sT0IXBt3_kyI,4921
238
238
  ultralytics/utils/autodevice.py,sha256=OKZfTbswg6SlsYGCGMqROkA-451CXGG47oeyC5Q1kFM,7232
239
239
  ultralytics/utils/benchmarks.py,sha256=lDNNnLeLUzmqKrqrqlCOiau-q7A-gcLooZP2dbxCu-U,30214
240
- ultralytics/utils/checks.py,sha256=L5G8CiQo8v2842KLGOaLG5y_AYRoa5gxCdtTt48LnS0,33129
240
+ ultralytics/utils/checks.py,sha256=TGhnnNVT3NEBhSeckWIe1rGlXUyYI3xhFqK6CR0oBiE,33192
241
241
  ultralytics/utils/dist.py,sha256=aytW0JEkcA5ZTZucV92ot7Bn-apiej8aLk3QNWicjAc,4103
242
242
  ultralytics/utils/downloads.py,sha256=Rn8xDwn2bzgBqiYz3Xn0rm3MWjk4T-QUd2Ajlu1EpQ4,22312
243
243
  ultralytics/utils/errors.py,sha256=vY9h2evFSrHnZdHJVVrmm8Zzw4qVDLyo9DeYW5g0dFk,1573
@@ -245,10 +245,10 @@ ultralytics/utils/export.py,sha256=XInnl9AQeik7EuR1492nzDvgDqaV43FlnM5CLamrgd4,8
245
245
  ultralytics/utils/files.py,sha256=0K4O1cgqRiXaDw7EQK13TqA5SME_RrvfDVQSPetNr5w,8042
246
246
  ultralytics/utils/instance.py,sha256=UOEsXR9V-bXNRk6BTonASBEgeMqvzzAk4S7VdXZJUAM,18090
247
247
  ultralytics/utils/loss.py,sha256=Woc_rj7ptCyezHdylEygXMeSEgivYu_B9jJHD4UwxWE,37607
248
- ultralytics/utils/metrics.py,sha256=pWNq-66VqkMjj05Gqkm8ddoElDK72q_U9cl8y-aEN6k,53963
248
+ ultralytics/utils/metrics.py,sha256=n8guPEADBMRNpeXNShEX-fxVv9xck8S4QaOIiaW_kl0,56037
249
249
  ultralytics/utils/ops.py,sha256=YFwPrKlPcgEmgAWqnJVR0Ccx5NQgp5e3P-YYHwVSP0k,34779
250
250
  ultralytics/utils/patches.py,sha256=_dhIU_eDklQE-aWIjpyjPHl_wOwZoGuIUQnXgdSwk_A,5020
251
- ultralytics/utils/plotting.py,sha256=m9Hsbt6U073jAiztX6clpd9KzznW62oHxCWlBcm0T-s,46920
251
+ ultralytics/utils/plotting.py,sha256=GKic2OMavjJPT3pOPdU0UcvQTrG1LVt0vHJM-Zuy9Bs,47217
252
252
  ultralytics/utils/tal.py,sha256=P5nPoR9qNnFuDIda0fsn8WP6m1V8r7EbvXUuhNRFFTA,20805
253
253
  ultralytics/utils/torch_utils.py,sha256=2SJxxg8Qr0YqOoQ-8qAYn6VrzZdQMObqiw3CJZ-rAY0,39611
254
254
  ultralytics/utils/triton.py,sha256=xK9Db_ZUVDnIK1u76S2G-6ulIBsLfj9HN_YOaSrnMuU,5304
@@ -264,9 +264,9 @@ ultralytics/utils/callbacks/neptune.py,sha256=yYUgEgSv6L39sSev6vjwhAWU3DlPDsbSDV
264
264
  ultralytics/utils/callbacks/raytune.py,sha256=A8amUGpux7dYES-L1iSeMoMXBySGWCD1aUqT7vcG-pU,1284
265
265
  ultralytics/utils/callbacks/tensorboard.py,sha256=jgYnym3cUQFAgN1GzTyO7l3jINtfAh8zhrllDvnLuVQ,5339
266
266
  ultralytics/utils/callbacks/wb.py,sha256=iDRFXI4IIDm8R5OI89DMTmjs8aHLo1HRCLkOFKdaMG4,7507
267
- ultralytics-8.3.135.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
268
- ultralytics-8.3.135.dist-info/METADATA,sha256=fukeo8lOpErZd4N34nFV-AH8hNzKpuYnOjWniPl0JQ4,37231
269
- ultralytics-8.3.135.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
270
- ultralytics-8.3.135.dist-info/entry_points.txt,sha256=YM_wiKyTe9yRrsEfqvYolNO5ngwfoL4-NwgKzc8_7sI,93
271
- ultralytics-8.3.135.dist-info/top_level.txt,sha256=XP49TwiMw4QGsvTLSYiJhz1xF_k7ev5mQ8jJXaXi45Q,12
272
- ultralytics-8.3.135.dist-info/RECORD,,
267
+ ultralytics-8.3.136.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
268
+ ultralytics-8.3.136.dist-info/METADATA,sha256=_0wkrDo-3iree01UfTJ_ayCZ0Wsjt0JtFvNzwwn02jc,37200
269
+ ultralytics-8.3.136.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
270
+ ultralytics-8.3.136.dist-info/entry_points.txt,sha256=YM_wiKyTe9yRrsEfqvYolNO5ngwfoL4-NwgKzc8_7sI,93
271
+ ultralytics-8.3.136.dist-info/top_level.txt,sha256=XP49TwiMw4QGsvTLSYiJhz1xF_k7ev5mQ8jJXaXi45Q,12
272
+ ultralytics-8.3.136.dist-info/RECORD,,