dgenerate-ultralytics-headless 8.3.241__py3-none-any.whl → 8.3.243__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 (30) hide show
  1. {dgenerate_ultralytics_headless-8.3.241.dist-info → dgenerate_ultralytics_headless-8.3.243.dist-info}/METADATA +2 -2
  2. {dgenerate_ultralytics_headless-8.3.241.dist-info → dgenerate_ultralytics_headless-8.3.243.dist-info}/RECORD +30 -30
  3. tests/test_exports.py +1 -2
  4. ultralytics/__init__.py +1 -1
  5. ultralytics/cfg/__init__.py +1 -1
  6. ultralytics/data/augment.py +3 -2
  7. ultralytics/engine/exporter.py +16 -22
  8. ultralytics/engine/tuner.py +2 -1
  9. ultralytics/models/sam/predict.py +9 -6
  10. ultralytics/models/sam/sam3/encoder.py +0 -6
  11. ultralytics/models/sam/sam3/model_misc.py +2 -1
  12. ultralytics/models/sam/sam3/vitdet.py +2 -1
  13. ultralytics/models/yolo/detect/predict.py +2 -1
  14. ultralytics/nn/autobackend.py +3 -5
  15. ultralytics/nn/modules/block.py +7 -5
  16. ultralytics/nn/modules/head.py +3 -2
  17. ultralytics/trackers/utils/matching.py +1 -1
  18. ultralytics/utils/callbacks/platform.py +255 -38
  19. ultralytics/utils/checks.py +5 -0
  20. ultralytics/utils/export/imx.py +2 -2
  21. ultralytics/utils/git.py +2 -1
  22. ultralytics/utils/logger.py +131 -75
  23. ultralytics/utils/loss.py +6 -8
  24. ultralytics/utils/metrics.py +2 -1
  25. ultralytics/utils/ops.py +4 -3
  26. ultralytics/utils/tqdm.py +2 -1
  27. {dgenerate_ultralytics_headless-8.3.241.dist-info → dgenerate_ultralytics_headless-8.3.243.dist-info}/WHEEL +0 -0
  28. {dgenerate_ultralytics_headless-8.3.241.dist-info → dgenerate_ultralytics_headless-8.3.243.dist-info}/entry_points.txt +0 -0
  29. {dgenerate_ultralytics_headless-8.3.241.dist-info → dgenerate_ultralytics_headless-8.3.243.dist-info}/licenses/LICENSE +0 -0
  30. {dgenerate_ultralytics_headless-8.3.241.dist-info → dgenerate_ultralytics_headless-8.3.243.dist-info}/top_level.txt +0 -0
ultralytics/utils/loss.py CHANGED
@@ -498,7 +498,7 @@ class v8PoseLoss(v8DetectionLoss):
498
498
 
499
499
  def __call__(self, preds: Any, batch: dict[str, torch.Tensor]) -> tuple[torch.Tensor, torch.Tensor]:
500
500
  """Calculate the total loss and detach it for pose estimation."""
501
- loss = torch.zeros(5, device=self.device) # box, cls, dfl, kpt_location, kpt_visibility
501
+ loss = torch.zeros(5, device=self.device) # box, pose, kobj, cls, dfl
502
502
  feats, pred_kpts = preds if isinstance(preds[0], list) else preds[1]
503
503
  pred_distri, pred_scores = torch.cat([xi.view(feats[0].shape[0], self.no, -1) for xi in feats], 2).split(
504
504
  (self.reg_max * 4, self.nc), 1
@@ -560,7 +560,7 @@ class v8PoseLoss(v8DetectionLoss):
560
560
  loss[3] *= self.hyp.cls # cls gain
561
561
  loss[4] *= self.hyp.dfl # dfl gain
562
562
 
563
- return loss * batch_size, loss.detach() # loss(box, cls, dfl)
563
+ return loss * batch_size, loss.detach() # loss(box, pose, kobj, cls, dfl)
564
564
 
565
565
  @staticmethod
566
566
  def kpts_decode(anchor_points: torch.Tensor, pred_kpts: torch.Tensor) -> torch.Tensor:
@@ -684,7 +684,7 @@ class v8OBBLoss(v8DetectionLoss):
684
684
  """Calculate and return the loss for oriented bounding box detection."""
685
685
  loss = torch.zeros(3, device=self.device) # box, cls, dfl
686
686
  feats, pred_angle = preds if isinstance(preds[0], list) else preds[1]
687
- batch_size = pred_angle.shape[0] # batch size, number of masks, mask height, mask width
687
+ batch_size = pred_angle.shape[0] # batch size
688
688
  pred_distri, pred_scores = torch.cat([xi.view(feats[0].shape[0], self.no, -1) for xi in feats], 2).split(
689
689
  (self.reg_max * 4, self.nc), 1
690
690
  )
@@ -702,7 +702,7 @@ class v8OBBLoss(v8DetectionLoss):
702
702
  try:
703
703
  batch_idx = batch["batch_idx"].view(-1, 1)
704
704
  targets = torch.cat((batch_idx, batch["cls"].view(-1, 1), batch["bboxes"].view(-1, 5)), 1)
705
- rw, rh = targets[:, 4] * imgsz[0].item(), targets[:, 5] * imgsz[1].item()
705
+ rw, rh = targets[:, 4] * float(imgsz[1]), targets[:, 5] * float(imgsz[0])
706
706
  targets = targets[(rw >= 2) & (rh >= 2)] # filter rboxes of tiny size to stabilize training
707
707
  targets = self.preprocess(targets, batch_size, scale_tensor=imgsz[[1, 0, 1, 0]])
708
708
  gt_labels, gt_bboxes = targets.split((1, 5), 2) # cls, xywhr
@@ -803,7 +803,6 @@ class TVPDetectLoss:
803
803
  def __call__(self, preds: Any, batch: dict[str, torch.Tensor]) -> tuple[torch.Tensor, torch.Tensor]:
804
804
  """Calculate the loss for text-visual prompt detection."""
805
805
  feats = preds[1] if isinstance(preds, tuple) else preds
806
- assert self.ori_reg_max == self.vp_criterion.reg_max # TODO: remove it
807
806
 
808
807
  if self.ori_reg_max * 4 + self.ori_nc == feats[0].shape[1]:
809
808
  loss = torch.zeros(3, device=self.vp_criterion.device, requires_grad=True)
@@ -811,8 +810,8 @@ class TVPDetectLoss:
811
810
 
812
811
  vp_feats = self._get_vp_features(feats)
813
812
  vp_loss = self.vp_criterion(vp_feats, batch)
814
- box_loss = vp_loss[0][1]
815
- return box_loss, vp_loss[1]
813
+ cls_loss = vp_loss[0][1]
814
+ return cls_loss, vp_loss[1]
816
815
 
817
816
  def _get_vp_features(self, feats: list[torch.Tensor]) -> list[torch.Tensor]:
818
817
  """Extract visual-prompt features from the model output."""
@@ -839,7 +838,6 @@ class TVPSegmentLoss(TVPDetectLoss):
839
838
  def __call__(self, preds: Any, batch: dict[str, torch.Tensor]) -> tuple[torch.Tensor, torch.Tensor]:
840
839
  """Calculate the loss for text-visual prompt segmentation."""
841
840
  feats, pred_masks, proto = preds if len(preds) == 3 else preds[1]
842
- assert self.ori_reg_max == self.vp_criterion.reg_max # TODO: remove it
843
841
 
844
842
  if self.ori_reg_max * 4 + self.ori_nc == feats[0].shape[1]:
845
843
  loss = torch.zeros(4, device=self.vp_criterion.device, requires_grad=True)
@@ -194,7 +194,8 @@ def _get_covariance_matrix(boxes: torch.Tensor) -> tuple[torch.Tensor, torch.Ten
194
194
  boxes (torch.Tensor): A tensor of shape (N, 5) representing rotated bounding boxes, with xywhr format.
195
195
 
196
196
  Returns:
197
- (torch.Tensor): Covariance matrices corresponding to original rotated bounding boxes.
197
+ (tuple[torch.Tensor, torch.Tensor, torch.Tensor]): Covariance matrix components (a, b, c) where the covariance
198
+ matrix is [[a, c], [c, b]], each of shape (N, 1).
198
199
  """
199
200
  # Gaussian bounding boxes, ignore the center points (the first two columns) because they are not needed here.
200
201
  gbbs = torch.cat((boxes[:, 2:4].pow(2) / 12, boxes[:, 4:]), dim=-1)
ultralytics/utils/ops.py CHANGED
@@ -604,11 +604,11 @@ def regularize_rboxes(rboxes):
604
604
  return torch.stack([x, y, w_, h_, t], dim=-1) # regularized boxes
605
605
 
606
606
 
607
- def masks2segments(masks, strategy: str = "all"):
607
+ def masks2segments(masks: np.ndarray | torch.Tensor, strategy: str = "all") -> list[np.ndarray]:
608
608
  """Convert masks to segments using contour detection.
609
609
 
610
610
  Args:
611
- masks (torch.Tensor): Binary masks with shape (batch_size, 160, 160).
611
+ masks (np.ndarray | torch.Tensor): Binary masks with shape (batch_size, 160, 160).
612
612
  strategy (str): Segmentation strategy, either 'all' or 'largest'.
613
613
 
614
614
  Returns:
@@ -616,8 +616,9 @@ def masks2segments(masks, strategy: str = "all"):
616
616
  """
617
617
  from ultralytics.data.converter import merge_multi_segment
618
618
 
619
+ masks = masks.astype("uint8") if isinstance(masks, np.ndarray) else masks.byte().cpu().numpy()
619
620
  segments = []
620
- for x in masks.byte().cpu().numpy():
621
+ for x in np.ascontiguousarray(masks):
621
622
  c = cv2.findContours(x, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
622
623
  if c:
623
624
  if strategy == "all": # merge and concatenate all segments
ultralytics/utils/tqdm.py CHANGED
@@ -179,7 +179,8 @@ class TQDM:
179
179
  num /= self.unit_divisor
180
180
  return f"{num:.1f}PB"
181
181
 
182
- def _format_time(self, seconds: float) -> str:
182
+ @staticmethod
183
+ def _format_time(seconds: float) -> str:
183
184
  """Format time duration."""
184
185
  if seconds < 60:
185
186
  return f"{seconds:.1f}s"