dgenerate-ultralytics-headless 8.3.189__py3-none-any.whl → 8.3.191__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.
Files changed (111) hide show
  1. {dgenerate_ultralytics_headless-8.3.189.dist-info → dgenerate_ultralytics_headless-8.3.191.dist-info}/METADATA +1 -1
  2. {dgenerate_ultralytics_headless-8.3.189.dist-info → dgenerate_ultralytics_headless-8.3.191.dist-info}/RECORD +111 -109
  3. tests/test_cuda.py +6 -5
  4. tests/test_exports.py +1 -6
  5. tests/test_python.py +1 -4
  6. tests/test_solutions.py +1 -1
  7. ultralytics/__init__.py +1 -1
  8. ultralytics/cfg/__init__.py +16 -14
  9. ultralytics/cfg/datasets/VisDrone.yaml +4 -4
  10. ultralytics/data/annotator.py +6 -6
  11. ultralytics/data/augment.py +53 -51
  12. ultralytics/data/base.py +15 -13
  13. ultralytics/data/build.py +7 -4
  14. ultralytics/data/converter.py +9 -10
  15. ultralytics/data/dataset.py +24 -22
  16. ultralytics/data/loaders.py +13 -11
  17. ultralytics/data/split.py +4 -3
  18. ultralytics/data/split_dota.py +14 -12
  19. ultralytics/data/utils.py +31 -25
  20. ultralytics/engine/exporter.py +7 -4
  21. ultralytics/engine/model.py +16 -14
  22. ultralytics/engine/predictor.py +9 -7
  23. ultralytics/engine/results.py +59 -57
  24. ultralytics/engine/trainer.py +7 -0
  25. ultralytics/engine/tuner.py +4 -3
  26. ultralytics/engine/validator.py +3 -1
  27. ultralytics/hub/__init__.py +6 -2
  28. ultralytics/hub/auth.py +2 -2
  29. ultralytics/hub/google/__init__.py +9 -8
  30. ultralytics/hub/session.py +11 -11
  31. ultralytics/hub/utils.py +8 -9
  32. ultralytics/models/fastsam/model.py +8 -6
  33. ultralytics/models/nas/model.py +5 -3
  34. ultralytics/models/rtdetr/train.py +4 -3
  35. ultralytics/models/rtdetr/val.py +6 -4
  36. ultralytics/models/sam/amg.py +13 -10
  37. ultralytics/models/sam/model.py +3 -2
  38. ultralytics/models/sam/modules/blocks.py +21 -21
  39. ultralytics/models/sam/modules/decoders.py +11 -11
  40. ultralytics/models/sam/modules/encoders.py +25 -25
  41. ultralytics/models/sam/modules/memory_attention.py +9 -8
  42. ultralytics/models/sam/modules/sam.py +8 -10
  43. ultralytics/models/sam/modules/tiny_encoder.py +21 -20
  44. ultralytics/models/sam/modules/transformer.py +6 -5
  45. ultralytics/models/sam/modules/utils.py +7 -5
  46. ultralytics/models/sam/predict.py +32 -31
  47. ultralytics/models/utils/loss.py +29 -27
  48. ultralytics/models/utils/ops.py +10 -8
  49. ultralytics/models/yolo/classify/train.py +7 -5
  50. ultralytics/models/yolo/classify/val.py +10 -8
  51. ultralytics/models/yolo/detect/predict.py +3 -3
  52. ultralytics/models/yolo/detect/train.py +8 -6
  53. ultralytics/models/yolo/detect/val.py +23 -21
  54. ultralytics/models/yolo/model.py +14 -14
  55. ultralytics/models/yolo/obb/train.py +5 -3
  56. ultralytics/models/yolo/obb/val.py +13 -10
  57. ultralytics/models/yolo/pose/train.py +7 -5
  58. ultralytics/models/yolo/pose/val.py +11 -9
  59. ultralytics/models/yolo/segment/train.py +4 -5
  60. ultralytics/models/yolo/segment/val.py +12 -10
  61. ultralytics/models/yolo/world/train.py +9 -7
  62. ultralytics/models/yolo/yoloe/train.py +7 -6
  63. ultralytics/models/yolo/yoloe/val.py +10 -8
  64. ultralytics/nn/autobackend.py +40 -52
  65. ultralytics/nn/modules/__init__.py +3 -3
  66. ultralytics/nn/modules/block.py +12 -12
  67. ultralytics/nn/modules/conv.py +4 -3
  68. ultralytics/nn/modules/head.py +46 -38
  69. ultralytics/nn/modules/transformer.py +22 -21
  70. ultralytics/nn/tasks.py +2 -2
  71. ultralytics/nn/text_model.py +6 -5
  72. ultralytics/solutions/analytics.py +7 -5
  73. ultralytics/solutions/config.py +12 -10
  74. ultralytics/solutions/distance_calculation.py +3 -3
  75. ultralytics/solutions/heatmap.py +4 -2
  76. ultralytics/solutions/object_counter.py +5 -3
  77. ultralytics/solutions/parking_management.py +4 -2
  78. ultralytics/solutions/region_counter.py +7 -5
  79. ultralytics/solutions/similarity_search.py +5 -3
  80. ultralytics/solutions/solutions.py +38 -36
  81. ultralytics/solutions/streamlit_inference.py +8 -7
  82. ultralytics/trackers/bot_sort.py +11 -9
  83. ultralytics/trackers/byte_tracker.py +17 -15
  84. ultralytics/trackers/utils/gmc.py +4 -3
  85. ultralytics/utils/__init__.py +27 -77
  86. ultralytics/utils/autobatch.py +3 -2
  87. ultralytics/utils/autodevice.py +10 -10
  88. ultralytics/utils/benchmarks.py +11 -10
  89. ultralytics/utils/callbacks/comet.py +9 -9
  90. ultralytics/utils/callbacks/platform.py +2 -1
  91. ultralytics/utils/checks.py +20 -29
  92. ultralytics/utils/downloads.py +2 -2
  93. ultralytics/utils/export.py +12 -11
  94. ultralytics/utils/files.py +8 -7
  95. ultralytics/utils/git.py +139 -0
  96. ultralytics/utils/instance.py +8 -7
  97. ultralytics/utils/logger.py +7 -6
  98. ultralytics/utils/loss.py +15 -13
  99. ultralytics/utils/metrics.py +62 -62
  100. ultralytics/utils/nms.py +346 -0
  101. ultralytics/utils/ops.py +83 -251
  102. ultralytics/utils/patches.py +6 -4
  103. ultralytics/utils/plotting.py +18 -16
  104. ultralytics/utils/tal.py +1 -1
  105. ultralytics/utils/torch_utils.py +4 -2
  106. ultralytics/utils/tqdm.py +47 -33
  107. ultralytics/utils/triton.py +3 -2
  108. {dgenerate_ultralytics_headless-8.3.189.dist-info → dgenerate_ultralytics_headless-8.3.191.dist-info}/WHEEL +0 -0
  109. {dgenerate_ultralytics_headless-8.3.189.dist-info → dgenerate_ultralytics_headless-8.3.191.dist-info}/entry_points.txt +0 -0
  110. {dgenerate_ultralytics_headless-8.3.189.dist-info → dgenerate_ultralytics_headless-8.3.191.dist-info}/licenses/LICENSE +0 -0
  111. {dgenerate_ultralytics_headless-8.3.189.dist-info → dgenerate_ultralytics_headless-8.3.191.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,8 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
- from typing import Any, Dict, List, Optional, Tuple
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
4
6
 
5
7
  import torch
6
8
  import torch.nn as nn
@@ -36,7 +38,7 @@ class DETRLoss(nn.Module):
36
38
  def __init__(
37
39
  self,
38
40
  nc: int = 80,
39
- loss_gain: Optional[Dict[str, float]] = None,
41
+ loss_gain: dict[str, float] | None = None,
40
42
  aux_loss: bool = True,
41
43
  use_fl: bool = True,
42
44
  use_vfl: bool = False,
@@ -79,7 +81,7 @@ class DETRLoss(nn.Module):
79
81
 
80
82
  def _get_loss_class(
81
83
  self, pred_scores: torch.Tensor, targets: torch.Tensor, gt_scores: torch.Tensor, num_gts: int, postfix: str = ""
82
- ) -> Dict[str, torch.Tensor]:
84
+ ) -> dict[str, torch.Tensor]:
83
85
  """
84
86
  Compute classification loss based on predictions, target values, and ground truth scores.
85
87
 
@@ -121,7 +123,7 @@ class DETRLoss(nn.Module):
121
123
 
122
124
  def _get_loss_bbox(
123
125
  self, pred_bboxes: torch.Tensor, gt_bboxes: torch.Tensor, postfix: str = ""
124
- ) -> Dict[str, torch.Tensor]:
126
+ ) -> dict[str, torch.Tensor]:
125
127
  """
126
128
  Compute bounding box and GIoU losses for predicted and ground truth bounding boxes.
127
129
 
@@ -191,12 +193,12 @@ class DETRLoss(nn.Module):
191
193
  pred_scores: torch.Tensor,
192
194
  gt_bboxes: torch.Tensor,
193
195
  gt_cls: torch.Tensor,
194
- gt_groups: List[int],
195
- match_indices: Optional[List[Tuple]] = None,
196
+ gt_groups: list[int],
197
+ match_indices: list[tuple] | None = None,
196
198
  postfix: str = "",
197
- masks: Optional[torch.Tensor] = None,
198
- gt_mask: Optional[torch.Tensor] = None,
199
- ) -> Dict[str, torch.Tensor]:
199
+ masks: torch.Tensor | None = None,
200
+ gt_mask: torch.Tensor | None = None,
201
+ ) -> dict[str, torch.Tensor]:
200
202
  """
201
203
  Get auxiliary losses for intermediate decoder layers.
202
204
 
@@ -258,7 +260,7 @@ class DETRLoss(nn.Module):
258
260
  return loss
259
261
 
260
262
  @staticmethod
261
- def _get_index(match_indices: List[Tuple]) -> Tuple[Tuple[torch.Tensor, torch.Tensor], torch.Tensor]:
263
+ def _get_index(match_indices: list[tuple]) -> tuple[tuple[torch.Tensor, torch.Tensor], torch.Tensor]:
262
264
  """
263
265
  Extract batch indices, source indices, and destination indices from match indices.
264
266
 
@@ -275,8 +277,8 @@ class DETRLoss(nn.Module):
275
277
  return (batch_idx, src_idx), dst_idx
276
278
 
277
279
  def _get_assigned_bboxes(
278
- self, pred_bboxes: torch.Tensor, gt_bboxes: torch.Tensor, match_indices: List[Tuple]
279
- ) -> Tuple[torch.Tensor, torch.Tensor]:
280
+ self, pred_bboxes: torch.Tensor, gt_bboxes: torch.Tensor, match_indices: list[tuple]
281
+ ) -> tuple[torch.Tensor, torch.Tensor]:
280
282
  """
281
283
  Assign predicted bounding boxes to ground truth bounding boxes based on match indices.
282
284
 
@@ -309,12 +311,12 @@ class DETRLoss(nn.Module):
309
311
  pred_scores: torch.Tensor,
310
312
  gt_bboxes: torch.Tensor,
311
313
  gt_cls: torch.Tensor,
312
- gt_groups: List[int],
313
- masks: Optional[torch.Tensor] = None,
314
- gt_mask: Optional[torch.Tensor] = None,
314
+ gt_groups: list[int],
315
+ masks: torch.Tensor | None = None,
316
+ gt_mask: torch.Tensor | None = None,
315
317
  postfix: str = "",
316
- match_indices: Optional[List[Tuple]] = None,
317
- ) -> Dict[str, torch.Tensor]:
318
+ match_indices: list[tuple] | None = None,
319
+ ) -> dict[str, torch.Tensor]:
318
320
  """
319
321
  Calculate losses for a single prediction layer.
320
322
 
@@ -358,10 +360,10 @@ class DETRLoss(nn.Module):
358
360
  self,
359
361
  pred_bboxes: torch.Tensor,
360
362
  pred_scores: torch.Tensor,
361
- batch: Dict[str, Any],
363
+ batch: dict[str, Any],
362
364
  postfix: str = "",
363
365
  **kwargs: Any,
364
- ) -> Dict[str, torch.Tensor]:
366
+ ) -> dict[str, torch.Tensor]:
365
367
  """
366
368
  Calculate loss for predicted bounding boxes and scores.
367
369
 
@@ -407,12 +409,12 @@ class RTDETRDetectionLoss(DETRLoss):
407
409
 
408
410
  def forward(
409
411
  self,
410
- preds: Tuple[torch.Tensor, torch.Tensor],
411
- batch: Dict[str, Any],
412
- dn_bboxes: Optional[torch.Tensor] = None,
413
- dn_scores: Optional[torch.Tensor] = None,
414
- dn_meta: Optional[Dict[str, Any]] = None,
415
- ) -> Dict[str, torch.Tensor]:
412
+ preds: tuple[torch.Tensor, torch.Tensor],
413
+ batch: dict[str, Any],
414
+ dn_bboxes: torch.Tensor | None = None,
415
+ dn_scores: torch.Tensor | None = None,
416
+ dn_meta: dict[str, Any] | None = None,
417
+ ) -> dict[str, torch.Tensor]:
416
418
  """
417
419
  Forward pass to compute detection loss with optional denoising loss.
418
420
 
@@ -448,8 +450,8 @@ class RTDETRDetectionLoss(DETRLoss):
448
450
 
449
451
  @staticmethod
450
452
  def get_dn_match_indices(
451
- dn_pos_idx: List[torch.Tensor], dn_num_group: int, gt_groups: List[int]
452
- ) -> List[Tuple[torch.Tensor, torch.Tensor]]:
453
+ dn_pos_idx: list[torch.Tensor], dn_num_group: int, gt_groups: list[int]
454
+ ) -> list[tuple[torch.Tensor, torch.Tensor]]:
453
455
  """
454
456
  Get match indices for denoising.
455
457
 
@@ -1,6 +1,8 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
- from typing import Any, Dict, List, Optional, Tuple
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
4
6
 
5
7
  import torch
6
8
  import torch.nn as nn
@@ -47,7 +49,7 @@ class HungarianMatcher(nn.Module):
47
49
 
48
50
  def __init__(
49
51
  self,
50
- cost_gain: Optional[Dict[str, float]] = None,
52
+ cost_gain: dict[str, float] | None = None,
51
53
  use_fl: bool = True,
52
54
  with_mask: bool = False,
53
55
  num_sample_points: int = 12544,
@@ -82,10 +84,10 @@ class HungarianMatcher(nn.Module):
82
84
  pred_scores: torch.Tensor,
83
85
  gt_bboxes: torch.Tensor,
84
86
  gt_cls: torch.Tensor,
85
- gt_groups: List[int],
86
- masks: Optional[torch.Tensor] = None,
87
- gt_mask: Optional[List[torch.Tensor]] = None,
88
- ) -> List[Tuple[torch.Tensor, torch.Tensor]]:
87
+ gt_groups: list[int],
88
+ masks: torch.Tensor | None = None,
89
+ gt_mask: list[torch.Tensor] | None = None,
90
+ ) -> list[tuple[torch.Tensor, torch.Tensor]]:
89
91
  """
90
92
  Compute optimal assignment between predictions and ground truth using Hungarian algorithm.
91
93
 
@@ -187,7 +189,7 @@ class HungarianMatcher(nn.Module):
187
189
 
188
190
 
189
191
  def get_cdn_group(
190
- batch: Dict[str, Any],
192
+ batch: dict[str, Any],
191
193
  num_classes: int,
192
194
  num_queries: int,
193
195
  class_embed: torch.Tensor,
@@ -195,7 +197,7 @@ def get_cdn_group(
195
197
  cls_noise_ratio: float = 0.5,
196
198
  box_noise_scale: float = 1.0,
197
199
  training: bool = False,
198
- ) -> Tuple[Optional[torch.Tensor], Optional[torch.Tensor], Optional[torch.Tensor], Optional[Dict[str, Any]]]:
200
+ ) -> tuple[torch.Tensor | None, torch.Tensor | None, torch.Tensor | None, dict[str, Any] | None]:
199
201
  """
200
202
  Generate contrastive denoising training group with positive and negative samples from ground truths.
201
203
 
@@ -1,7 +1,9 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  from copy import copy
4
- from typing import Any, Dict, Optional
6
+ from typing import Any
5
7
 
6
8
  import torch
7
9
 
@@ -49,7 +51,7 @@ class ClassificationTrainer(BaseTrainer):
49
51
  >>> trainer.train()
50
52
  """
51
53
 
52
- def __init__(self, cfg=DEFAULT_CFG, overrides: Optional[Dict[str, Any]] = None, _callbacks=None):
54
+ def __init__(self, cfg=DEFAULT_CFG, overrides: dict[str, Any] | None = None, _callbacks=None):
53
55
  """
54
56
  Initialize a ClassificationTrainer object.
55
57
 
@@ -162,7 +164,7 @@ class ClassificationTrainer(BaseTrainer):
162
164
  self.model.transforms = loader.dataset.torch_transforms
163
165
  return loader
164
166
 
165
- def preprocess_batch(self, batch: Dict[str, torch.Tensor]) -> Dict[str, torch.Tensor]:
167
+ def preprocess_batch(self, batch: dict[str, torch.Tensor]) -> dict[str, torch.Tensor]:
166
168
  """Preprocess a batch of images and classes."""
167
169
  batch["img"] = batch["img"].to(self.device)
168
170
  batch["cls"] = batch["cls"].to(self.device)
@@ -185,7 +187,7 @@ class ClassificationTrainer(BaseTrainer):
185
187
  self.test_loader, self.save_dir, args=copy(self.args), _callbacks=self.callbacks
186
188
  )
187
189
 
188
- def label_loss_items(self, loss_items: Optional[torch.Tensor] = None, prefix: str = "train"):
190
+ def label_loss_items(self, loss_items: torch.Tensor | None = None, prefix: str = "train"):
189
191
  """
190
192
  Return a loss dict with labelled training loss items tensor.
191
193
 
@@ -220,7 +222,7 @@ class ClassificationTrainer(BaseTrainer):
220
222
  self.metrics.pop("fitness", None)
221
223
  self.run_callbacks("on_fit_epoch_end")
222
224
 
223
- def plot_training_samples(self, batch: Dict[str, torch.Tensor], ni: int):
225
+ def plot_training_samples(self, batch: dict[str, torch.Tensor], ni: int):
224
226
  """
225
227
  Plot training samples with their annotations.
226
228
 
@@ -1,7 +1,9 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  from pathlib import Path
4
- from typing import Any, Dict, List, Tuple, Union
6
+ from typing import Any
5
7
 
6
8
  import torch
7
9
 
@@ -85,14 +87,14 @@ class ClassificationValidator(BaseValidator):
85
87
  self.targets = []
86
88
  self.confusion_matrix = ConfusionMatrix(names=model.names)
87
89
 
88
- def preprocess(self, batch: Dict[str, Any]) -> Dict[str, Any]:
90
+ def preprocess(self, batch: dict[str, Any]) -> dict[str, Any]:
89
91
  """Preprocess input batch by moving data to device and converting to appropriate dtype."""
90
92
  batch["img"] = batch["img"].to(self.device, non_blocking=True)
91
93
  batch["img"] = batch["img"].half() if self.args.half else batch["img"].float()
92
94
  batch["cls"] = batch["cls"].to(self.device)
93
95
  return batch
94
96
 
95
- def update_metrics(self, preds: torch.Tensor, batch: Dict[str, Any]) -> None:
97
+ def update_metrics(self, preds: torch.Tensor, batch: dict[str, Any]) -> None:
96
98
  """
97
99
  Update running metrics with model predictions and batch targets.
98
100
 
@@ -131,11 +133,11 @@ class ClassificationValidator(BaseValidator):
131
133
  self.metrics.save_dir = self.save_dir
132
134
  self.metrics.confusion_matrix = self.confusion_matrix
133
135
 
134
- def postprocess(self, preds: Union[torch.Tensor, List[torch.Tensor], Tuple[torch.Tensor]]) -> torch.Tensor:
136
+ def postprocess(self, preds: torch.Tensor | list[torch.Tensor] | tuple[torch.Tensor]) -> torch.Tensor:
135
137
  """Extract the primary prediction from model output if it's in a list or tuple format."""
136
138
  return preds[0] if isinstance(preds, (list, tuple)) else preds
137
139
 
138
- def get_stats(self) -> Dict[str, float]:
140
+ def get_stats(self) -> dict[str, float]:
139
141
  """Calculate and return a dictionary of metrics by processing targets and predictions."""
140
142
  self.metrics.process(self.targets, self.pred)
141
143
  return self.metrics.results_dict
@@ -144,7 +146,7 @@ class ClassificationValidator(BaseValidator):
144
146
  """Create a ClassificationDataset instance for validation."""
145
147
  return ClassificationDataset(root=img_path, args=self.args, augment=False, prefix=self.args.split)
146
148
 
147
- def get_dataloader(self, dataset_path: Union[Path, str], batch_size: int) -> torch.utils.data.DataLoader:
149
+ def get_dataloader(self, dataset_path: Path | str, batch_size: int) -> torch.utils.data.DataLoader:
148
150
  """
149
151
  Build and return a data loader for classification validation.
150
152
 
@@ -163,7 +165,7 @@ class ClassificationValidator(BaseValidator):
163
165
  pf = "%22s" + "%11.3g" * len(self.metrics.keys) # print format
164
166
  LOGGER.info(pf % ("all", self.metrics.top1, self.metrics.top5))
165
167
 
166
- def plot_val_samples(self, batch: Dict[str, Any], ni: int) -> None:
168
+ def plot_val_samples(self, batch: dict[str, Any], ni: int) -> None:
167
169
  """
168
170
  Plot validation image samples with their ground truth labels.
169
171
 
@@ -184,7 +186,7 @@ class ClassificationValidator(BaseValidator):
184
186
  on_plot=self.on_plot,
185
187
  )
186
188
 
187
- def plot_predictions(self, batch: Dict[str, Any], preds: torch.Tensor, ni: int) -> None:
189
+ def plot_predictions(self, batch: dict[str, Any], preds: torch.Tensor, ni: int) -> None:
188
190
  """
189
191
  Plot images with their predicted class labels and save the visualization.
190
192
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  from ultralytics.engine.predictor import BasePredictor
4
4
  from ultralytics.engine.results import Results
5
- from ultralytics.utils import ops
5
+ from ultralytics.utils import nms, ops
6
6
 
7
7
 
8
8
  class DetectionPredictor(BasePredictor):
@@ -53,7 +53,7 @@ class DetectionPredictor(BasePredictor):
53
53
  >>> processed_results = predictor.postprocess(preds, img, orig_imgs)
54
54
  """
55
55
  save_feats = getattr(self, "_feats", None) is not None
56
- preds = ops.non_max_suppression(
56
+ preds = nms.non_max_suppression(
57
57
  preds,
58
58
  self.args.conf,
59
59
  self.args.iou,
@@ -85,7 +85,7 @@ class DetectionPredictor(BasePredictor):
85
85
  """Extract object features from the feature maps."""
86
86
  import torch
87
87
 
88
- s = min([x.shape[1] for x in feat_maps]) # find smallest vector length
88
+ s = min(x.shape[1] for x in feat_maps) # find shortest vector length
89
89
  obj_feats = torch.cat(
90
90
  [x.permute(0, 2, 3, 1).reshape(x.shape[0], -1, s, x.shape[1] // s).mean(dim=-1) for x in feat_maps], dim=1
91
91
  ) # mean reduce all vectors to same length
@@ -1,9 +1,11 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import math
4
6
  import random
5
7
  from copy import copy
6
- from typing import Any, Dict, List, Optional
8
+ from typing import Any
7
9
 
8
10
  import numpy as np
9
11
  import torch.nn as nn
@@ -51,7 +53,7 @@ class DetectionTrainer(BaseTrainer):
51
53
  >>> trainer.train()
52
54
  """
53
55
 
54
- def build_dataset(self, img_path: str, mode: str = "train", batch: Optional[int] = None):
56
+ def build_dataset(self, img_path: str, mode: str = "train", batch: int | None = None):
55
57
  """
56
58
  Build YOLO Dataset for training or validation.
57
59
 
@@ -89,7 +91,7 @@ class DetectionTrainer(BaseTrainer):
89
91
  workers = self.args.workers if mode == "train" else self.args.workers * 2
90
92
  return build_dataloader(dataset, batch_size, workers, shuffle, rank) # return dataloader
91
93
 
92
- def preprocess_batch(self, batch: Dict) -> Dict:
94
+ def preprocess_batch(self, batch: dict) -> dict:
93
95
  """
94
96
  Preprocess a batch of images by scaling and converting to float.
95
97
 
@@ -127,7 +129,7 @@ class DetectionTrainer(BaseTrainer):
127
129
  self.model.args = self.args # attach hyperparameters to model
128
130
  # TODO: self.model.class_weights = labels_to_class_weights(dataset.labels, nc).to(device) * nc
129
131
 
130
- def get_model(self, cfg: Optional[str] = None, weights: Optional[str] = None, verbose: bool = True):
132
+ def get_model(self, cfg: str | None = None, weights: str | None = None, verbose: bool = True):
131
133
  """
132
134
  Return a YOLO detection model.
133
135
 
@@ -151,7 +153,7 @@ class DetectionTrainer(BaseTrainer):
151
153
  self.test_loader, save_dir=self.save_dir, args=copy(self.args), _callbacks=self.callbacks
152
154
  )
153
155
 
154
- def label_loss_items(self, loss_items: Optional[List[float]] = None, prefix: str = "train"):
156
+ def label_loss_items(self, loss_items: list[float] | None = None, prefix: str = "train"):
155
157
  """
156
158
  Return a loss dict with labeled training loss items tensor.
157
159
 
@@ -179,7 +181,7 @@ class DetectionTrainer(BaseTrainer):
179
181
  "Size",
180
182
  )
181
183
 
182
- def plot_training_samples(self, batch: Dict[str, Any], ni: int) -> None:
184
+ def plot_training_samples(self, batch: dict[str, Any], ni: int) -> None:
183
185
  """
184
186
  Plot training samples with their annotations.
185
187
 
@@ -1,15 +1,17 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import os
4
6
  from pathlib import Path
5
- from typing import Any, Dict, List, Optional, Tuple, Union
7
+ from typing import Any
6
8
 
7
9
  import numpy as np
8
10
  import torch
9
11
 
10
12
  from ultralytics.data import build_dataloader, build_yolo_dataset, converter
11
13
  from ultralytics.engine.validator import BaseValidator
12
- from ultralytics.utils import LOGGER, ops
14
+ from ultralytics.utils import LOGGER, nms, ops
13
15
  from ultralytics.utils.checks import check_requirements
14
16
  from ultralytics.utils.metrics import ConfusionMatrix, DetMetrics, box_iou
15
17
  from ultralytics.utils.plotting import plot_images
@@ -59,7 +61,7 @@ class DetectionValidator(BaseValidator):
59
61
  self.niou = self.iouv.numel()
60
62
  self.metrics = DetMetrics()
61
63
 
62
- def preprocess(self, batch: Dict[str, Any]) -> Dict[str, Any]:
64
+ def preprocess(self, batch: dict[str, Any]) -> dict[str, Any]:
63
65
  """
64
66
  Preprocess batch of images for YOLO validation.
65
67
 
@@ -104,7 +106,7 @@ class DetectionValidator(BaseValidator):
104
106
  """Return a formatted string summarizing class metrics of YOLO model."""
105
107
  return ("%22s" + "%11s" * 6) % ("Class", "Images", "Instances", "Box(P", "R", "mAP50", "mAP50-95)")
106
108
 
107
- def postprocess(self, preds: torch.Tensor) -> List[Dict[str, torch.Tensor]]:
109
+ def postprocess(self, preds: torch.Tensor) -> list[dict[str, torch.Tensor]]:
108
110
  """
109
111
  Apply Non-maximum suppression to prediction outputs.
110
112
 
@@ -115,7 +117,7 @@ class DetectionValidator(BaseValidator):
115
117
  (List[Dict[str, torch.Tensor]]): Processed predictions after NMS, where each dict contains
116
118
  'bboxes', 'conf', 'cls', and 'extra' tensors.
117
119
  """
118
- outputs = ops.non_max_suppression(
120
+ outputs = nms.non_max_suppression(
119
121
  preds,
120
122
  self.args.conf,
121
123
  self.args.iou,
@@ -128,7 +130,7 @@ class DetectionValidator(BaseValidator):
128
130
  )
129
131
  return [{"bboxes": x[:, :4], "conf": x[:, 4], "cls": x[:, 5], "extra": x[:, 6:]} for x in outputs]
130
132
 
131
- def _prepare_batch(self, si: int, batch: Dict[str, Any]) -> Dict[str, Any]:
133
+ def _prepare_batch(self, si: int, batch: dict[str, Any]) -> dict[str, Any]:
132
134
  """
133
135
  Prepare a batch of images and annotations for validation.
134
136
 
@@ -156,7 +158,7 @@ class DetectionValidator(BaseValidator):
156
158
  "im_file": batch["im_file"][si],
157
159
  }
158
160
 
159
- def _prepare_pred(self, pred: Dict[str, torch.Tensor]) -> Dict[str, torch.Tensor]:
161
+ def _prepare_pred(self, pred: dict[str, torch.Tensor]) -> dict[str, torch.Tensor]:
160
162
  """
161
163
  Prepare predictions for evaluation against ground truth.
162
164
 
@@ -170,7 +172,7 @@ class DetectionValidator(BaseValidator):
170
172
  pred["cls"] *= 0
171
173
  return pred
172
174
 
173
- def update_metrics(self, preds: List[Dict[str, torch.Tensor]], batch: Dict[str, Any]) -> None:
175
+ def update_metrics(self, preds: list[dict[str, torch.Tensor]], batch: dict[str, Any]) -> None:
174
176
  """
175
177
  Update metrics with new predictions and ground truth.
176
178
 
@@ -225,7 +227,7 @@ class DetectionValidator(BaseValidator):
225
227
  self.metrics.confusion_matrix = self.confusion_matrix
226
228
  self.metrics.save_dir = self.save_dir
227
229
 
228
- def get_stats(self) -> Dict[str, Any]:
230
+ def get_stats(self) -> dict[str, Any]:
229
231
  """
230
232
  Calculate and return metrics statistics.
231
233
 
@@ -256,7 +258,7 @@ class DetectionValidator(BaseValidator):
256
258
  )
257
259
  )
258
260
 
259
- def _process_batch(self, preds: Dict[str, torch.Tensor], batch: Dict[str, Any]) -> Dict[str, np.ndarray]:
261
+ def _process_batch(self, preds: dict[str, torch.Tensor], batch: dict[str, Any]) -> dict[str, np.ndarray]:
260
262
  """
261
263
  Return correct prediction matrix.
262
264
 
@@ -272,7 +274,7 @@ class DetectionValidator(BaseValidator):
272
274
  iou = box_iou(batch["bboxes"], preds["bboxes"])
273
275
  return {"tp": self.match_predictions(preds["cls"], batch["cls"], iou).cpu().numpy()}
274
276
 
275
- def build_dataset(self, img_path: str, mode: str = "val", batch: Optional[int] = None) -> torch.utils.data.Dataset:
277
+ def build_dataset(self, img_path: str, mode: str = "val", batch: int | None = None) -> torch.utils.data.Dataset:
276
278
  """
277
279
  Build YOLO Dataset.
278
280
 
@@ -300,7 +302,7 @@ class DetectionValidator(BaseValidator):
300
302
  dataset = self.build_dataset(dataset_path, batch=batch_size, mode="val")
301
303
  return build_dataloader(dataset, batch_size, self.args.workers, shuffle=False, rank=-1) # return dataloader
302
304
 
303
- def plot_val_samples(self, batch: Dict[str, Any], ni: int) -> None:
305
+ def plot_val_samples(self, batch: dict[str, Any], ni: int) -> None:
304
306
  """
305
307
  Plot validation image samples.
306
308
 
@@ -317,7 +319,7 @@ class DetectionValidator(BaseValidator):
317
319
  )
318
320
 
319
321
  def plot_predictions(
320
- self, batch: Dict[str, Any], preds: List[Dict[str, torch.Tensor]], ni: int, max_det: Optional[int] = None
322
+ self, batch: dict[str, Any], preds: list[dict[str, torch.Tensor]], ni: int, max_det: int | None = None
321
323
  ) -> None:
322
324
  """
323
325
  Plot predicted bounding boxes on input images and save the result.
@@ -345,7 +347,7 @@ class DetectionValidator(BaseValidator):
345
347
  on_plot=self.on_plot,
346
348
  ) # pred
347
349
 
348
- def save_one_txt(self, predn: Dict[str, torch.Tensor], save_conf: bool, shape: Tuple[int, int], file: Path) -> None:
350
+ def save_one_txt(self, predn: dict[str, torch.Tensor], save_conf: bool, shape: tuple[int, int], file: Path) -> None:
349
351
  """
350
352
  Save YOLO detections to a txt file in normalized coordinates in a specific format.
351
353
 
@@ -364,7 +366,7 @@ class DetectionValidator(BaseValidator):
364
366
  boxes=torch.cat([predn["bboxes"], predn["conf"].unsqueeze(-1), predn["cls"].unsqueeze(-1)], dim=1),
365
367
  ).save_txt(file, save_conf=save_conf)
366
368
 
367
- def pred_to_json(self, predn: Dict[str, torch.Tensor], pbatch: Dict[str, Any]) -> None:
369
+ def pred_to_json(self, predn: dict[str, torch.Tensor], pbatch: dict[str, Any]) -> None:
368
370
  """
369
371
  Serialize YOLO predictions to COCO json format.
370
372
 
@@ -398,7 +400,7 @@ class DetectionValidator(BaseValidator):
398
400
  }
399
401
  )
400
402
 
401
- def scale_preds(self, predn: Dict[str, torch.Tensor], pbatch: Dict[str, Any]) -> Dict[str, torch.Tensor]:
403
+ def scale_preds(self, predn: dict[str, torch.Tensor], pbatch: dict[str, Any]) -> dict[str, torch.Tensor]:
402
404
  """Scales predictions to the original image size."""
403
405
  return {
404
406
  **predn,
@@ -410,7 +412,7 @@ class DetectionValidator(BaseValidator):
410
412
  ),
411
413
  }
412
414
 
413
- def eval_json(self, stats: Dict[str, Any]) -> Dict[str, Any]:
415
+ def eval_json(self, stats: dict[str, Any]) -> dict[str, Any]:
414
416
  """
415
417
  Evaluate YOLO output in JSON format and return performance statistics.
416
418
 
@@ -430,12 +432,12 @@ class DetectionValidator(BaseValidator):
430
432
 
431
433
  def coco_evaluate(
432
434
  self,
433
- stats: Dict[str, Any],
435
+ stats: dict[str, Any],
434
436
  pred_json: str,
435
437
  anno_json: str,
436
- iou_types: Union[str, List[str]] = "bbox",
437
- suffix: Union[str, List[str]] = "Box",
438
- ) -> Dict[str, Any]:
438
+ iou_types: str | list[str] = "bbox",
439
+ suffix: str | list[str] = "Box",
440
+ ) -> dict[str, Any]:
439
441
  """
440
442
  Evaluate COCO/LVIS metrics using faster-coco-eval library.
441
443
 
@@ -1,7 +1,9 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  from pathlib import Path
4
- from typing import Any, Dict, List, Optional, Union
6
+ from typing import Any
5
7
 
6
8
  import torch
7
9
 
@@ -49,7 +51,7 @@ class YOLO(Model):
49
51
  >>> model = YOLO("yolo11n.yaml")
50
52
  """
51
53
 
52
- def __init__(self, model: Union[str, Path] = "yolo11n.pt", task: Optional[str] = None, verbose: bool = False):
54
+ def __init__(self, model: str | Path = "yolo11n.pt", task: str | None = None, verbose: bool = False):
53
55
  """
54
56
  Initialize a YOLO model.
55
57
 
@@ -87,7 +89,7 @@ class YOLO(Model):
87
89
  self.__dict__ = new_instance.__dict__
88
90
 
89
91
  @property
90
- def task_map(self) -> Dict[str, Dict[str, Any]]:
92
+ def task_map(self) -> dict[str, dict[str, Any]]:
91
93
  """Map head to model, trainer, validator, and predictor classes."""
92
94
  return {
93
95
  "classify": {
@@ -149,7 +151,7 @@ class YOLOWorld(Model):
149
151
  >>> model.set_classes(["person", "car", "bicycle"])
150
152
  """
151
153
 
152
- def __init__(self, model: Union[str, Path] = "yolov8s-world.pt", verbose: bool = False) -> None:
154
+ def __init__(self, model: str | Path = "yolov8s-world.pt", verbose: bool = False) -> None:
153
155
  """
154
156
  Initialize YOLOv8-World model with a pre-trained model file.
155
157
 
@@ -167,7 +169,7 @@ class YOLOWorld(Model):
167
169
  self.model.names = YAML.load(ROOT / "cfg/datasets/coco8.yaml").get("names")
168
170
 
169
171
  @property
170
- def task_map(self) -> Dict[str, Dict[str, Any]]:
172
+ def task_map(self) -> dict[str, dict[str, Any]]:
171
173
  """Map head to model, validator, and predictor classes."""
172
174
  return {
173
175
  "detect": {
@@ -178,7 +180,7 @@ class YOLOWorld(Model):
178
180
  }
179
181
  }
180
182
 
181
- def set_classes(self, classes: List[str]) -> None:
183
+ def set_classes(self, classes: list[str]) -> None:
182
184
  """
183
185
  Set the model's class names for detection.
184
186
 
@@ -232,9 +234,7 @@ class YOLOE(Model):
232
234
  >>> results = model.predict("image.jpg", visual_prompts=prompts)
233
235
  """
234
236
 
235
- def __init__(
236
- self, model: Union[str, Path] = "yoloe-11s-seg.pt", task: Optional[str] = None, verbose: bool = False
237
- ) -> None:
237
+ def __init__(self, model: str | Path = "yoloe-11s-seg.pt", task: str | None = None, verbose: bool = False) -> None:
238
238
  """
239
239
  Initialize YOLOE model with a pre-trained model file.
240
240
 
@@ -246,7 +246,7 @@ class YOLOE(Model):
246
246
  super().__init__(model=model, task=task, verbose=verbose)
247
247
 
248
248
  @property
249
- def task_map(self) -> Dict[str, Dict[str, Any]]:
249
+ def task_map(self) -> dict[str, dict[str, Any]]:
250
250
  """Map head to model, validator, and predictor classes."""
251
251
  return {
252
252
  "detect": {
@@ -291,7 +291,7 @@ class YOLOE(Model):
291
291
  assert isinstance(self.model, YOLOEModel)
292
292
  return self.model.get_visual_pe(img, visual)
293
293
 
294
- def set_vocab(self, vocab: List[str], names: List[str]) -> None:
294
+ def set_vocab(self, vocab: list[str], names: list[str]) -> None:
295
295
  """
296
296
  Set vocabulary and class names for the YOLOE model.
297
297
 
@@ -317,7 +317,7 @@ class YOLOE(Model):
317
317
  assert isinstance(self.model, YOLOEModel)
318
318
  return self.model.get_vocab(names)
319
319
 
320
- def set_classes(self, classes: List[str], embeddings: Optional[torch.Tensor] = None) -> None:
320
+ def set_classes(self, classes: list[str], embeddings: torch.Tensor | None = None) -> None:
321
321
  """
322
322
  Set the model's class names and embeddings for detection.
323
323
 
@@ -341,7 +341,7 @@ class YOLOE(Model):
341
341
  self,
342
342
  validator=None,
343
343
  load_vp: bool = False,
344
- refer_data: Optional[str] = None,
344
+ refer_data: str | None = None,
345
345
  **kwargs,
346
346
  ):
347
347
  """
@@ -368,7 +368,7 @@ class YOLOE(Model):
368
368
  self,
369
369
  source=None,
370
370
  stream: bool = False,
371
- visual_prompts: Dict[str, List] = {},
371
+ visual_prompts: dict[str, list] = {},
372
372
  refer_image=None,
373
373
  predictor=yolo.yoloe.YOLOEVPDetectPredictor,
374
374
  **kwargs,