dgenerate-ultralytics-headless 8.3.134__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 (272) hide show
  1. dgenerate_ultralytics_headless-8.3.134.dist-info/METADATA +400 -0
  2. dgenerate_ultralytics_headless-8.3.134.dist-info/RECORD +272 -0
  3. dgenerate_ultralytics_headless-8.3.134.dist-info/WHEEL +5 -0
  4. dgenerate_ultralytics_headless-8.3.134.dist-info/entry_points.txt +3 -0
  5. dgenerate_ultralytics_headless-8.3.134.dist-info/licenses/LICENSE +661 -0
  6. dgenerate_ultralytics_headless-8.3.134.dist-info/top_level.txt +1 -0
  7. tests/__init__.py +22 -0
  8. tests/conftest.py +83 -0
  9. tests/test_cli.py +138 -0
  10. tests/test_cuda.py +215 -0
  11. tests/test_engine.py +131 -0
  12. tests/test_exports.py +236 -0
  13. tests/test_integrations.py +154 -0
  14. tests/test_python.py +694 -0
  15. tests/test_solutions.py +187 -0
  16. ultralytics/__init__.py +30 -0
  17. ultralytics/assets/bus.jpg +0 -0
  18. ultralytics/assets/zidane.jpg +0 -0
  19. ultralytics/cfg/__init__.py +1023 -0
  20. ultralytics/cfg/datasets/Argoverse.yaml +77 -0
  21. ultralytics/cfg/datasets/DOTAv1.5.yaml +37 -0
  22. ultralytics/cfg/datasets/DOTAv1.yaml +36 -0
  23. ultralytics/cfg/datasets/GlobalWheat2020.yaml +68 -0
  24. ultralytics/cfg/datasets/HomeObjects-3K.yaml +33 -0
  25. ultralytics/cfg/datasets/ImageNet.yaml +2025 -0
  26. ultralytics/cfg/datasets/Objects365.yaml +443 -0
  27. ultralytics/cfg/datasets/SKU-110K.yaml +58 -0
  28. ultralytics/cfg/datasets/VOC.yaml +106 -0
  29. ultralytics/cfg/datasets/VisDrone.yaml +77 -0
  30. ultralytics/cfg/datasets/african-wildlife.yaml +25 -0
  31. ultralytics/cfg/datasets/brain-tumor.yaml +23 -0
  32. ultralytics/cfg/datasets/carparts-seg.yaml +44 -0
  33. ultralytics/cfg/datasets/coco-pose.yaml +42 -0
  34. ultralytics/cfg/datasets/coco.yaml +118 -0
  35. ultralytics/cfg/datasets/coco128-seg.yaml +101 -0
  36. ultralytics/cfg/datasets/coco128.yaml +101 -0
  37. ultralytics/cfg/datasets/coco8-multispectral.yaml +104 -0
  38. ultralytics/cfg/datasets/coco8-pose.yaml +26 -0
  39. ultralytics/cfg/datasets/coco8-seg.yaml +101 -0
  40. ultralytics/cfg/datasets/coco8.yaml +101 -0
  41. ultralytics/cfg/datasets/crack-seg.yaml +22 -0
  42. ultralytics/cfg/datasets/dog-pose.yaml +24 -0
  43. ultralytics/cfg/datasets/dota8-multispectral.yaml +38 -0
  44. ultralytics/cfg/datasets/dota8.yaml +35 -0
  45. ultralytics/cfg/datasets/hand-keypoints.yaml +26 -0
  46. ultralytics/cfg/datasets/lvis.yaml +1240 -0
  47. ultralytics/cfg/datasets/medical-pills.yaml +22 -0
  48. ultralytics/cfg/datasets/open-images-v7.yaml +666 -0
  49. ultralytics/cfg/datasets/package-seg.yaml +22 -0
  50. ultralytics/cfg/datasets/signature.yaml +21 -0
  51. ultralytics/cfg/datasets/tiger-pose.yaml +25 -0
  52. ultralytics/cfg/datasets/xView.yaml +155 -0
  53. ultralytics/cfg/default.yaml +127 -0
  54. ultralytics/cfg/models/11/yolo11-cls-resnet18.yaml +17 -0
  55. ultralytics/cfg/models/11/yolo11-cls.yaml +33 -0
  56. ultralytics/cfg/models/11/yolo11-obb.yaml +50 -0
  57. ultralytics/cfg/models/11/yolo11-pose.yaml +51 -0
  58. ultralytics/cfg/models/11/yolo11-seg.yaml +50 -0
  59. ultralytics/cfg/models/11/yolo11.yaml +50 -0
  60. ultralytics/cfg/models/11/yoloe-11-seg.yaml +48 -0
  61. ultralytics/cfg/models/11/yoloe-11.yaml +48 -0
  62. ultralytics/cfg/models/12/yolo12-cls.yaml +32 -0
  63. ultralytics/cfg/models/12/yolo12-obb.yaml +48 -0
  64. ultralytics/cfg/models/12/yolo12-pose.yaml +49 -0
  65. ultralytics/cfg/models/12/yolo12-seg.yaml +48 -0
  66. ultralytics/cfg/models/12/yolo12.yaml +48 -0
  67. ultralytics/cfg/models/rt-detr/rtdetr-l.yaml +53 -0
  68. ultralytics/cfg/models/rt-detr/rtdetr-resnet101.yaml +45 -0
  69. ultralytics/cfg/models/rt-detr/rtdetr-resnet50.yaml +45 -0
  70. ultralytics/cfg/models/rt-detr/rtdetr-x.yaml +57 -0
  71. ultralytics/cfg/models/v10/yolov10b.yaml +45 -0
  72. ultralytics/cfg/models/v10/yolov10l.yaml +45 -0
  73. ultralytics/cfg/models/v10/yolov10m.yaml +45 -0
  74. ultralytics/cfg/models/v10/yolov10n.yaml +45 -0
  75. ultralytics/cfg/models/v10/yolov10s.yaml +45 -0
  76. ultralytics/cfg/models/v10/yolov10x.yaml +45 -0
  77. ultralytics/cfg/models/v3/yolov3-spp.yaml +49 -0
  78. ultralytics/cfg/models/v3/yolov3-tiny.yaml +40 -0
  79. ultralytics/cfg/models/v3/yolov3.yaml +49 -0
  80. ultralytics/cfg/models/v5/yolov5-p6.yaml +62 -0
  81. ultralytics/cfg/models/v5/yolov5.yaml +51 -0
  82. ultralytics/cfg/models/v6/yolov6.yaml +56 -0
  83. ultralytics/cfg/models/v8/yoloe-v8-seg.yaml +45 -0
  84. ultralytics/cfg/models/v8/yoloe-v8.yaml +45 -0
  85. ultralytics/cfg/models/v8/yolov8-cls-resnet101.yaml +28 -0
  86. ultralytics/cfg/models/v8/yolov8-cls-resnet50.yaml +28 -0
  87. ultralytics/cfg/models/v8/yolov8-cls.yaml +32 -0
  88. ultralytics/cfg/models/v8/yolov8-ghost-p2.yaml +58 -0
  89. ultralytics/cfg/models/v8/yolov8-ghost-p6.yaml +60 -0
  90. ultralytics/cfg/models/v8/yolov8-ghost.yaml +50 -0
  91. ultralytics/cfg/models/v8/yolov8-obb.yaml +49 -0
  92. ultralytics/cfg/models/v8/yolov8-p2.yaml +57 -0
  93. ultralytics/cfg/models/v8/yolov8-p6.yaml +59 -0
  94. ultralytics/cfg/models/v8/yolov8-pose-p6.yaml +60 -0
  95. ultralytics/cfg/models/v8/yolov8-pose.yaml +50 -0
  96. ultralytics/cfg/models/v8/yolov8-rtdetr.yaml +49 -0
  97. ultralytics/cfg/models/v8/yolov8-seg-p6.yaml +59 -0
  98. ultralytics/cfg/models/v8/yolov8-seg.yaml +49 -0
  99. ultralytics/cfg/models/v8/yolov8-world.yaml +51 -0
  100. ultralytics/cfg/models/v8/yolov8-worldv2.yaml +49 -0
  101. ultralytics/cfg/models/v8/yolov8.yaml +49 -0
  102. ultralytics/cfg/models/v9/yolov9c-seg.yaml +41 -0
  103. ultralytics/cfg/models/v9/yolov9c.yaml +41 -0
  104. ultralytics/cfg/models/v9/yolov9e-seg.yaml +64 -0
  105. ultralytics/cfg/models/v9/yolov9e.yaml +64 -0
  106. ultralytics/cfg/models/v9/yolov9m.yaml +41 -0
  107. ultralytics/cfg/models/v9/yolov9s.yaml +41 -0
  108. ultralytics/cfg/models/v9/yolov9t.yaml +41 -0
  109. ultralytics/cfg/trackers/botsort.yaml +22 -0
  110. ultralytics/cfg/trackers/bytetrack.yaml +14 -0
  111. ultralytics/data/__init__.py +26 -0
  112. ultralytics/data/annotator.py +66 -0
  113. ultralytics/data/augment.py +2945 -0
  114. ultralytics/data/base.py +438 -0
  115. ultralytics/data/build.py +258 -0
  116. ultralytics/data/converter.py +754 -0
  117. ultralytics/data/dataset.py +834 -0
  118. ultralytics/data/loaders.py +676 -0
  119. ultralytics/data/scripts/download_weights.sh +18 -0
  120. ultralytics/data/scripts/get_coco.sh +61 -0
  121. ultralytics/data/scripts/get_coco128.sh +18 -0
  122. ultralytics/data/scripts/get_imagenet.sh +52 -0
  123. ultralytics/data/split.py +125 -0
  124. ultralytics/data/split_dota.py +325 -0
  125. ultralytics/data/utils.py +777 -0
  126. ultralytics/engine/__init__.py +1 -0
  127. ultralytics/engine/exporter.py +1519 -0
  128. ultralytics/engine/model.py +1156 -0
  129. ultralytics/engine/predictor.py +502 -0
  130. ultralytics/engine/results.py +1840 -0
  131. ultralytics/engine/trainer.py +853 -0
  132. ultralytics/engine/tuner.py +243 -0
  133. ultralytics/engine/validator.py +377 -0
  134. ultralytics/hub/__init__.py +168 -0
  135. ultralytics/hub/auth.py +137 -0
  136. ultralytics/hub/google/__init__.py +176 -0
  137. ultralytics/hub/session.py +446 -0
  138. ultralytics/hub/utils.py +248 -0
  139. ultralytics/models/__init__.py +9 -0
  140. ultralytics/models/fastsam/__init__.py +7 -0
  141. ultralytics/models/fastsam/model.py +61 -0
  142. ultralytics/models/fastsam/predict.py +181 -0
  143. ultralytics/models/fastsam/utils.py +24 -0
  144. ultralytics/models/fastsam/val.py +40 -0
  145. ultralytics/models/nas/__init__.py +7 -0
  146. ultralytics/models/nas/model.py +102 -0
  147. ultralytics/models/nas/predict.py +58 -0
  148. ultralytics/models/nas/val.py +39 -0
  149. ultralytics/models/rtdetr/__init__.py +7 -0
  150. ultralytics/models/rtdetr/model.py +63 -0
  151. ultralytics/models/rtdetr/predict.py +84 -0
  152. ultralytics/models/rtdetr/train.py +85 -0
  153. ultralytics/models/rtdetr/val.py +191 -0
  154. ultralytics/models/sam/__init__.py +6 -0
  155. ultralytics/models/sam/amg.py +260 -0
  156. ultralytics/models/sam/build.py +358 -0
  157. ultralytics/models/sam/model.py +170 -0
  158. ultralytics/models/sam/modules/__init__.py +1 -0
  159. ultralytics/models/sam/modules/blocks.py +1129 -0
  160. ultralytics/models/sam/modules/decoders.py +515 -0
  161. ultralytics/models/sam/modules/encoders.py +854 -0
  162. ultralytics/models/sam/modules/memory_attention.py +299 -0
  163. ultralytics/models/sam/modules/sam.py +1006 -0
  164. ultralytics/models/sam/modules/tiny_encoder.py +1002 -0
  165. ultralytics/models/sam/modules/transformer.py +351 -0
  166. ultralytics/models/sam/modules/utils.py +394 -0
  167. ultralytics/models/sam/predict.py +1605 -0
  168. ultralytics/models/utils/__init__.py +1 -0
  169. ultralytics/models/utils/loss.py +455 -0
  170. ultralytics/models/utils/ops.py +268 -0
  171. ultralytics/models/yolo/__init__.py +7 -0
  172. ultralytics/models/yolo/classify/__init__.py +7 -0
  173. ultralytics/models/yolo/classify/predict.py +88 -0
  174. ultralytics/models/yolo/classify/train.py +233 -0
  175. ultralytics/models/yolo/classify/val.py +215 -0
  176. ultralytics/models/yolo/detect/__init__.py +7 -0
  177. ultralytics/models/yolo/detect/predict.py +124 -0
  178. ultralytics/models/yolo/detect/train.py +217 -0
  179. ultralytics/models/yolo/detect/val.py +451 -0
  180. ultralytics/models/yolo/model.py +354 -0
  181. ultralytics/models/yolo/obb/__init__.py +7 -0
  182. ultralytics/models/yolo/obb/predict.py +66 -0
  183. ultralytics/models/yolo/obb/train.py +81 -0
  184. ultralytics/models/yolo/obb/val.py +283 -0
  185. ultralytics/models/yolo/pose/__init__.py +7 -0
  186. ultralytics/models/yolo/pose/predict.py +79 -0
  187. ultralytics/models/yolo/pose/train.py +154 -0
  188. ultralytics/models/yolo/pose/val.py +394 -0
  189. ultralytics/models/yolo/segment/__init__.py +7 -0
  190. ultralytics/models/yolo/segment/predict.py +113 -0
  191. ultralytics/models/yolo/segment/train.py +123 -0
  192. ultralytics/models/yolo/segment/val.py +428 -0
  193. ultralytics/models/yolo/world/__init__.py +5 -0
  194. ultralytics/models/yolo/world/train.py +119 -0
  195. ultralytics/models/yolo/world/train_world.py +176 -0
  196. ultralytics/models/yolo/yoloe/__init__.py +22 -0
  197. ultralytics/models/yolo/yoloe/predict.py +169 -0
  198. ultralytics/models/yolo/yoloe/train.py +298 -0
  199. ultralytics/models/yolo/yoloe/train_seg.py +124 -0
  200. ultralytics/models/yolo/yoloe/val.py +191 -0
  201. ultralytics/nn/__init__.py +29 -0
  202. ultralytics/nn/autobackend.py +842 -0
  203. ultralytics/nn/modules/__init__.py +182 -0
  204. ultralytics/nn/modules/activation.py +53 -0
  205. ultralytics/nn/modules/block.py +1966 -0
  206. ultralytics/nn/modules/conv.py +712 -0
  207. ultralytics/nn/modules/head.py +880 -0
  208. ultralytics/nn/modules/transformer.py +713 -0
  209. ultralytics/nn/modules/utils.py +164 -0
  210. ultralytics/nn/tasks.py +1627 -0
  211. ultralytics/nn/text_model.py +351 -0
  212. ultralytics/solutions/__init__.py +41 -0
  213. ultralytics/solutions/ai_gym.py +116 -0
  214. ultralytics/solutions/analytics.py +252 -0
  215. ultralytics/solutions/config.py +106 -0
  216. ultralytics/solutions/distance_calculation.py +124 -0
  217. ultralytics/solutions/heatmap.py +127 -0
  218. ultralytics/solutions/instance_segmentation.py +84 -0
  219. ultralytics/solutions/object_blurrer.py +90 -0
  220. ultralytics/solutions/object_counter.py +195 -0
  221. ultralytics/solutions/object_cropper.py +84 -0
  222. ultralytics/solutions/parking_management.py +273 -0
  223. ultralytics/solutions/queue_management.py +93 -0
  224. ultralytics/solutions/region_counter.py +120 -0
  225. ultralytics/solutions/security_alarm.py +154 -0
  226. ultralytics/solutions/similarity_search.py +172 -0
  227. ultralytics/solutions/solutions.py +724 -0
  228. ultralytics/solutions/speed_estimation.py +110 -0
  229. ultralytics/solutions/streamlit_inference.py +196 -0
  230. ultralytics/solutions/templates/similarity-search.html +160 -0
  231. ultralytics/solutions/trackzone.py +88 -0
  232. ultralytics/solutions/vision_eye.py +68 -0
  233. ultralytics/trackers/__init__.py +7 -0
  234. ultralytics/trackers/basetrack.py +124 -0
  235. ultralytics/trackers/bot_sort.py +260 -0
  236. ultralytics/trackers/byte_tracker.py +480 -0
  237. ultralytics/trackers/track.py +125 -0
  238. ultralytics/trackers/utils/__init__.py +1 -0
  239. ultralytics/trackers/utils/gmc.py +376 -0
  240. ultralytics/trackers/utils/kalman_filter.py +493 -0
  241. ultralytics/trackers/utils/matching.py +157 -0
  242. ultralytics/utils/__init__.py +1435 -0
  243. ultralytics/utils/autobatch.py +106 -0
  244. ultralytics/utils/autodevice.py +174 -0
  245. ultralytics/utils/benchmarks.py +695 -0
  246. ultralytics/utils/callbacks/__init__.py +5 -0
  247. ultralytics/utils/callbacks/base.py +234 -0
  248. ultralytics/utils/callbacks/clearml.py +153 -0
  249. ultralytics/utils/callbacks/comet.py +552 -0
  250. ultralytics/utils/callbacks/dvc.py +205 -0
  251. ultralytics/utils/callbacks/hub.py +108 -0
  252. ultralytics/utils/callbacks/mlflow.py +138 -0
  253. ultralytics/utils/callbacks/neptune.py +140 -0
  254. ultralytics/utils/callbacks/raytune.py +43 -0
  255. ultralytics/utils/callbacks/tensorboard.py +132 -0
  256. ultralytics/utils/callbacks/wb.py +185 -0
  257. ultralytics/utils/checks.py +897 -0
  258. ultralytics/utils/dist.py +119 -0
  259. ultralytics/utils/downloads.py +499 -0
  260. ultralytics/utils/errors.py +43 -0
  261. ultralytics/utils/export.py +219 -0
  262. ultralytics/utils/files.py +221 -0
  263. ultralytics/utils/instance.py +499 -0
  264. ultralytics/utils/loss.py +813 -0
  265. ultralytics/utils/metrics.py +1356 -0
  266. ultralytics/utils/ops.py +885 -0
  267. ultralytics/utils/patches.py +143 -0
  268. ultralytics/utils/plotting.py +1011 -0
  269. ultralytics/utils/tal.py +416 -0
  270. ultralytics/utils/torch_utils.py +990 -0
  271. ultralytics/utils/triton.py +116 -0
  272. ultralytics/utils/tuner.py +159 -0
@@ -0,0 +1 @@
1
+ # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
@@ -0,0 +1,455 @@
1
+ # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
+
3
+ import torch
4
+ import torch.nn as nn
5
+ import torch.nn.functional as F
6
+
7
+ from ultralytics.utils.loss import FocalLoss, VarifocalLoss
8
+ from ultralytics.utils.metrics import bbox_iou
9
+
10
+ from .ops import HungarianMatcher
11
+
12
+
13
+ class DETRLoss(nn.Module):
14
+ """
15
+ DETR (DEtection TRansformer) Loss class for calculating various loss components.
16
+
17
+ This class computes classification loss, bounding box loss, GIoU loss, and optionally auxiliary losses for the
18
+ DETR object detection model.
19
+
20
+ Attributes:
21
+ nc (int): Number of classes.
22
+ loss_gain (dict): Coefficients for different loss components.
23
+ aux_loss (bool): Whether to compute auxiliary losses.
24
+ use_fl (bool): Whether to use FocalLoss.
25
+ use_vfl (bool): Whether to use VarifocalLoss.
26
+ use_uni_match (bool): Whether to use a fixed layer for auxiliary branch label assignment.
27
+ uni_match_ind (int): Index of fixed layer to use if use_uni_match is True.
28
+ matcher (HungarianMatcher): Object to compute matching cost and indices.
29
+ fl (FocalLoss | None): Focal Loss object if use_fl is True, otherwise None.
30
+ vfl (VarifocalLoss | None): Varifocal Loss object if use_vfl is True, otherwise None.
31
+ device (torch.device): Device on which tensors are stored.
32
+ """
33
+
34
+ def __init__(
35
+ self,
36
+ nc=80,
37
+ loss_gain=None,
38
+ aux_loss=True,
39
+ use_fl=True,
40
+ use_vfl=False,
41
+ use_uni_match=False,
42
+ uni_match_ind=0,
43
+ gamma=1.5,
44
+ alpha=0.25,
45
+ ):
46
+ """
47
+ Initialize DETR loss function with customizable components and gains.
48
+
49
+ Uses default loss_gain if not provided. Initializes HungarianMatcher with preset cost gains. Supports auxiliary
50
+ losses and various loss types.
51
+
52
+ Args:
53
+ nc (int): Number of classes.
54
+ loss_gain (dict): Coefficients for different loss components.
55
+ aux_loss (bool): Whether to use auxiliary losses from each decoder layer.
56
+ use_fl (bool): Whether to use FocalLoss.
57
+ use_vfl (bool): Whether to use VarifocalLoss.
58
+ use_uni_match (bool): Whether to use fixed layer for auxiliary branch label assignment.
59
+ uni_match_ind (int): Index of fixed layer for uni_match.
60
+ gamma (float): The focusing parameter that controls how much the loss focuses on hard-to-classify examples.
61
+ alpha (float | list): The balancing factor used to address class imbalance.
62
+ """
63
+ super().__init__()
64
+
65
+ if loss_gain is None:
66
+ loss_gain = {"class": 1, "bbox": 5, "giou": 2, "no_object": 0.1, "mask": 1, "dice": 1}
67
+ self.nc = nc
68
+ self.matcher = HungarianMatcher(cost_gain={"class": 2, "bbox": 5, "giou": 2})
69
+ self.loss_gain = loss_gain
70
+ self.aux_loss = aux_loss
71
+ self.fl = FocalLoss(gamma, alpha) if use_fl else None
72
+ self.vfl = VarifocalLoss(gamma, alpha) if use_vfl else None
73
+
74
+ self.use_uni_match = use_uni_match
75
+ self.uni_match_ind = uni_match_ind
76
+ self.device = None
77
+
78
+ def _get_loss_class(self, pred_scores, targets, gt_scores, num_gts, postfix=""):
79
+ """
80
+ Compute classification loss based on predictions, target values, and ground truth scores.
81
+
82
+ Args:
83
+ pred_scores (torch.Tensor): Predicted class scores with shape (batch_size, num_queries, num_classes).
84
+ targets (torch.Tensor): Target class indices with shape (batch_size, num_queries).
85
+ gt_scores (torch.Tensor): Ground truth confidence scores with shape (batch_size, num_queries).
86
+ num_gts (int): Number of ground truth objects.
87
+ postfix (str, optional): String to append to the loss name for identification in multi-loss scenarios.
88
+
89
+ Returns:
90
+ loss_cls (torch.Tensor): Classification loss value.
91
+
92
+ Notes:
93
+ The function supports different classification loss types:
94
+ - Varifocal Loss (if self.vfl is True and num_gts > 0)
95
+ - Focal Loss (if self.fl is True)
96
+ - BCE Loss (default fallback)
97
+ """
98
+ # Logits: [b, query, num_classes], gt_class: list[[n, 1]]
99
+ name_class = f"loss_class{postfix}"
100
+ bs, nq = pred_scores.shape[:2]
101
+ # one_hot = F.one_hot(targets, self.nc + 1)[..., :-1] # (bs, num_queries, num_classes)
102
+ one_hot = torch.zeros((bs, nq, self.nc + 1), dtype=torch.int64, device=targets.device)
103
+ one_hot.scatter_(2, targets.unsqueeze(-1), 1)
104
+ one_hot = one_hot[..., :-1]
105
+ gt_scores = gt_scores.view(bs, nq, 1) * one_hot
106
+
107
+ if self.fl:
108
+ if num_gts and self.vfl:
109
+ loss_cls = self.vfl(pred_scores, gt_scores, one_hot)
110
+ else:
111
+ loss_cls = self.fl(pred_scores, one_hot.float())
112
+ loss_cls /= max(num_gts, 1) / nq
113
+ else:
114
+ loss_cls = nn.BCEWithLogitsLoss(reduction="none")(pred_scores, gt_scores).mean(1).sum() # YOLO CLS loss
115
+
116
+ return {name_class: loss_cls.squeeze() * self.loss_gain["class"]}
117
+
118
+ def _get_loss_bbox(self, pred_bboxes, gt_bboxes, postfix=""):
119
+ """
120
+ Compute bounding box and GIoU losses for predicted and ground truth bounding boxes.
121
+
122
+ Args:
123
+ pred_bboxes (torch.Tensor): Predicted bounding boxes with shape (batch_size, num_queries, 4).
124
+ gt_bboxes (torch.Tensor): Ground truth bounding boxes with shape (N, 4), where N is the total
125
+ number of ground truth boxes.
126
+ postfix (str): String to append to the loss names for identification in multi-loss scenarios.
127
+
128
+ Returns:
129
+ loss (dict): Dictionary containing:
130
+ - loss_bbox{postfix} (torch.Tensor): L1 loss between predicted and ground truth boxes,
131
+ scaled by the bbox loss gain.
132
+ - loss_giou{postfix} (torch.Tensor): GIoU loss between predicted and ground truth boxes,
133
+ scaled by the giou loss gain.
134
+
135
+ Notes:
136
+ If no ground truth boxes are provided (empty list), zero-valued tensors are returned for both losses.
137
+ """
138
+ # Boxes: [b, query, 4], gt_bbox: list[[n, 4]]
139
+ name_bbox = f"loss_bbox{postfix}"
140
+ name_giou = f"loss_giou{postfix}"
141
+
142
+ loss = {}
143
+ if len(gt_bboxes) == 0:
144
+ loss[name_bbox] = torch.tensor(0.0, device=self.device)
145
+ loss[name_giou] = torch.tensor(0.0, device=self.device)
146
+ return loss
147
+
148
+ loss[name_bbox] = self.loss_gain["bbox"] * F.l1_loss(pred_bboxes, gt_bboxes, reduction="sum") / len(gt_bboxes)
149
+ loss[name_giou] = 1.0 - bbox_iou(pred_bboxes, gt_bboxes, xywh=True, GIoU=True)
150
+ loss[name_giou] = loss[name_giou].sum() / len(gt_bboxes)
151
+ loss[name_giou] = self.loss_gain["giou"] * loss[name_giou]
152
+ return {k: v.squeeze() for k, v in loss.items()}
153
+
154
+ # This function is for future RT-DETR Segment models
155
+ # def _get_loss_mask(self, masks, gt_mask, match_indices, postfix=''):
156
+ # # masks: [b, query, h, w], gt_mask: list[[n, H, W]]
157
+ # name_mask = f'loss_mask{postfix}'
158
+ # name_dice = f'loss_dice{postfix}'
159
+ #
160
+ # loss = {}
161
+ # if sum(len(a) for a in gt_mask) == 0:
162
+ # loss[name_mask] = torch.tensor(0., device=self.device)
163
+ # loss[name_dice] = torch.tensor(0., device=self.device)
164
+ # return loss
165
+ #
166
+ # num_gts = len(gt_mask)
167
+ # src_masks, target_masks = self._get_assigned_bboxes(masks, gt_mask, match_indices)
168
+ # src_masks = F.interpolate(src_masks.unsqueeze(0), size=target_masks.shape[-2:], mode='bilinear')[0]
169
+ # # TODO: torch does not have `sigmoid_focal_loss`, but it's not urgent since we don't use mask branch for now.
170
+ # loss[name_mask] = self.loss_gain['mask'] * F.sigmoid_focal_loss(src_masks, target_masks,
171
+ # torch.tensor([num_gts], dtype=torch.float32))
172
+ # loss[name_dice] = self.loss_gain['dice'] * self._dice_loss(src_masks, target_masks, num_gts)
173
+ # return loss
174
+
175
+ # This function is for future RT-DETR Segment models
176
+ # @staticmethod
177
+ # def _dice_loss(inputs, targets, num_gts):
178
+ # inputs = F.sigmoid(inputs).flatten(1)
179
+ # targets = targets.flatten(1)
180
+ # numerator = 2 * (inputs * targets).sum(1)
181
+ # denominator = inputs.sum(-1) + targets.sum(-1)
182
+ # loss = 1 - (numerator + 1) / (denominator + 1)
183
+ # return loss.sum() / num_gts
184
+
185
+ def _get_loss_aux(
186
+ self,
187
+ pred_bboxes,
188
+ pred_scores,
189
+ gt_bboxes,
190
+ gt_cls,
191
+ gt_groups,
192
+ match_indices=None,
193
+ postfix="",
194
+ masks=None,
195
+ gt_mask=None,
196
+ ):
197
+ """
198
+ Get auxiliary losses for intermediate decoder layers.
199
+
200
+ Args:
201
+ pred_bboxes (torch.Tensor): Predicted bounding boxes from auxiliary layers.
202
+ pred_scores (torch.Tensor): Predicted scores from auxiliary layers.
203
+ gt_bboxes (torch.Tensor): Ground truth bounding boxes.
204
+ gt_cls (torch.Tensor): Ground truth classes.
205
+ gt_groups (List[int]): Number of ground truths per image.
206
+ match_indices (List[tuple], optional): Pre-computed matching indices.
207
+ postfix (str): String to append to loss names.
208
+ masks (torch.Tensor, optional): Predicted masks if using segmentation.
209
+ gt_mask (torch.Tensor, optional): Ground truth masks if using segmentation.
210
+
211
+ Returns:
212
+ (dict): Dictionary of auxiliary losses.
213
+ """
214
+ # NOTE: loss class, bbox, giou, mask, dice
215
+ loss = torch.zeros(5 if masks is not None else 3, device=pred_bboxes.device)
216
+ if match_indices is None and self.use_uni_match:
217
+ match_indices = self.matcher(
218
+ pred_bboxes[self.uni_match_ind],
219
+ pred_scores[self.uni_match_ind],
220
+ gt_bboxes,
221
+ gt_cls,
222
+ gt_groups,
223
+ masks=masks[self.uni_match_ind] if masks is not None else None,
224
+ gt_mask=gt_mask,
225
+ )
226
+ for i, (aux_bboxes, aux_scores) in enumerate(zip(pred_bboxes, pred_scores)):
227
+ aux_masks = masks[i] if masks is not None else None
228
+ loss_ = self._get_loss(
229
+ aux_bboxes,
230
+ aux_scores,
231
+ gt_bboxes,
232
+ gt_cls,
233
+ gt_groups,
234
+ masks=aux_masks,
235
+ gt_mask=gt_mask,
236
+ postfix=postfix,
237
+ match_indices=match_indices,
238
+ )
239
+ loss[0] += loss_[f"loss_class{postfix}"]
240
+ loss[1] += loss_[f"loss_bbox{postfix}"]
241
+ loss[2] += loss_[f"loss_giou{postfix}"]
242
+ # if masks is not None and gt_mask is not None:
243
+ # loss_ = self._get_loss_mask(aux_masks, gt_mask, match_indices, postfix)
244
+ # loss[3] += loss_[f'loss_mask{postfix}']
245
+ # loss[4] += loss_[f'loss_dice{postfix}']
246
+
247
+ loss = {
248
+ f"loss_class_aux{postfix}": loss[0],
249
+ f"loss_bbox_aux{postfix}": loss[1],
250
+ f"loss_giou_aux{postfix}": loss[2],
251
+ }
252
+ # if masks is not None and gt_mask is not None:
253
+ # loss[f'loss_mask_aux{postfix}'] = loss[3]
254
+ # loss[f'loss_dice_aux{postfix}'] = loss[4]
255
+ return loss
256
+
257
+ @staticmethod
258
+ def _get_index(match_indices):
259
+ """
260
+ Extract batch indices, source indices, and destination indices from match indices.
261
+
262
+ Args:
263
+ match_indices (List[tuple]): List of tuples containing matched indices.
264
+
265
+ Returns:
266
+ (tuple): Tuple containing (batch_idx, src_idx) and dst_idx.
267
+ """
268
+ batch_idx = torch.cat([torch.full_like(src, i) for i, (src, _) in enumerate(match_indices)])
269
+ src_idx = torch.cat([src for (src, _) in match_indices])
270
+ dst_idx = torch.cat([dst for (_, dst) in match_indices])
271
+ return (batch_idx, src_idx), dst_idx
272
+
273
+ def _get_assigned_bboxes(self, pred_bboxes, gt_bboxes, match_indices):
274
+ """
275
+ Assign predicted bounding boxes to ground truth bounding boxes based on match indices.
276
+
277
+ Args:
278
+ pred_bboxes (torch.Tensor): Predicted bounding boxes.
279
+ gt_bboxes (torch.Tensor): Ground truth bounding boxes.
280
+ match_indices (List[tuple]): List of tuples containing matched indices.
281
+
282
+ Returns:
283
+ (tuple): Tuple containing assigned predictions and ground truths.
284
+ """
285
+ pred_assigned = torch.cat(
286
+ [
287
+ t[i] if len(i) > 0 else torch.zeros(0, t.shape[-1], device=self.device)
288
+ for t, (i, _) in zip(pred_bboxes, match_indices)
289
+ ]
290
+ )
291
+ gt_assigned = torch.cat(
292
+ [
293
+ t[j] if len(j) > 0 else torch.zeros(0, t.shape[-1], device=self.device)
294
+ for t, (_, j) in zip(gt_bboxes, match_indices)
295
+ ]
296
+ )
297
+ return pred_assigned, gt_assigned
298
+
299
+ def _get_loss(
300
+ self,
301
+ pred_bboxes,
302
+ pred_scores,
303
+ gt_bboxes,
304
+ gt_cls,
305
+ gt_groups,
306
+ masks=None,
307
+ gt_mask=None,
308
+ postfix="",
309
+ match_indices=None,
310
+ ):
311
+ """
312
+ Calculate losses for a single prediction layer.
313
+
314
+ Args:
315
+ pred_bboxes (torch.Tensor): Predicted bounding boxes.
316
+ pred_scores (torch.Tensor): Predicted class scores.
317
+ gt_bboxes (torch.Tensor): Ground truth bounding boxes.
318
+ gt_cls (torch.Tensor): Ground truth classes.
319
+ gt_groups (List[int]): Number of ground truths per image.
320
+ masks (torch.Tensor, optional): Predicted masks if using segmentation.
321
+ gt_mask (torch.Tensor, optional): Ground truth masks if using segmentation.
322
+ postfix (str): String to append to loss names.
323
+ match_indices (List[tuple], optional): Pre-computed matching indices.
324
+
325
+ Returns:
326
+ (dict): Dictionary of losses.
327
+ """
328
+ if match_indices is None:
329
+ match_indices = self.matcher(
330
+ pred_bboxes, pred_scores, gt_bboxes, gt_cls, gt_groups, masks=masks, gt_mask=gt_mask
331
+ )
332
+
333
+ idx, gt_idx = self._get_index(match_indices)
334
+ pred_bboxes, gt_bboxes = pred_bboxes[idx], gt_bboxes[gt_idx]
335
+
336
+ bs, nq = pred_scores.shape[:2]
337
+ targets = torch.full((bs, nq), self.nc, device=pred_scores.device, dtype=gt_cls.dtype)
338
+ targets[idx] = gt_cls[gt_idx]
339
+
340
+ gt_scores = torch.zeros([bs, nq], device=pred_scores.device)
341
+ if len(gt_bboxes):
342
+ gt_scores[idx] = bbox_iou(pred_bboxes.detach(), gt_bboxes, xywh=True).squeeze(-1)
343
+
344
+ return {
345
+ **self._get_loss_class(pred_scores, targets, gt_scores, len(gt_bboxes), postfix),
346
+ **self._get_loss_bbox(pred_bboxes, gt_bboxes, postfix),
347
+ # **(self._get_loss_mask(masks, gt_mask, match_indices, postfix) if masks is not None and gt_mask is not None else {})
348
+ }
349
+
350
+ def forward(self, pred_bboxes, pred_scores, batch, postfix="", **kwargs):
351
+ """
352
+ Calculate loss for predicted bounding boxes and scores.
353
+
354
+ Args:
355
+ pred_bboxes (torch.Tensor): Predicted bounding boxes, shape [l, b, query, 4].
356
+ pred_scores (torch.Tensor): Predicted class scores, shape [l, b, query, num_classes].
357
+ batch (dict): Batch information containing:
358
+ cls (torch.Tensor): Ground truth classes, shape [num_gts].
359
+ bboxes (torch.Tensor): Ground truth bounding boxes, shape [num_gts, 4].
360
+ gt_groups (List[int]): Number of ground truths for each image in the batch.
361
+ postfix (str): Postfix for loss names.
362
+ **kwargs (Any): Additional arguments, may include 'match_indices'.
363
+
364
+ Returns:
365
+ (dict): Computed losses, including main and auxiliary (if enabled).
366
+
367
+ Notes:
368
+ Uses last elements of pred_bboxes and pred_scores for main loss, and the rest for auxiliary losses if
369
+ self.aux_loss is True.
370
+ """
371
+ self.device = pred_bboxes.device
372
+ match_indices = kwargs.get("match_indices", None)
373
+ gt_cls, gt_bboxes, gt_groups = batch["cls"], batch["bboxes"], batch["gt_groups"]
374
+
375
+ total_loss = self._get_loss(
376
+ pred_bboxes[-1], pred_scores[-1], gt_bboxes, gt_cls, gt_groups, postfix=postfix, match_indices=match_indices
377
+ )
378
+
379
+ if self.aux_loss:
380
+ total_loss.update(
381
+ self._get_loss_aux(
382
+ pred_bboxes[:-1], pred_scores[:-1], gt_bboxes, gt_cls, gt_groups, match_indices, postfix
383
+ )
384
+ )
385
+
386
+ return total_loss
387
+
388
+
389
+ class RTDETRDetectionLoss(DETRLoss):
390
+ """
391
+ Real-Time DeepTracker (RT-DETR) Detection Loss class that extends the DETRLoss.
392
+
393
+ This class computes the detection loss for the RT-DETR model, which includes the standard detection loss as well as
394
+ an additional denoising training loss when provided with denoising metadata.
395
+ """
396
+
397
+ def forward(self, preds, batch, dn_bboxes=None, dn_scores=None, dn_meta=None):
398
+ """
399
+ Forward pass to compute detection loss with optional denoising loss.
400
+
401
+ Args:
402
+ preds (tuple): Tuple containing predicted bounding boxes and scores.
403
+ batch (dict): Batch data containing ground truth information.
404
+ dn_bboxes (torch.Tensor, optional): Denoising bounding boxes.
405
+ dn_scores (torch.Tensor, optional): Denoising scores.
406
+ dn_meta (dict, optional): Metadata for denoising.
407
+
408
+ Returns:
409
+ (dict): Dictionary containing total loss and denoising loss if applicable.
410
+ """
411
+ pred_bboxes, pred_scores = preds
412
+ total_loss = super().forward(pred_bboxes, pred_scores, batch)
413
+
414
+ # Check for denoising metadata to compute denoising training loss
415
+ if dn_meta is not None:
416
+ dn_pos_idx, dn_num_group = dn_meta["dn_pos_idx"], dn_meta["dn_num_group"]
417
+ assert len(batch["gt_groups"]) == len(dn_pos_idx)
418
+
419
+ # Get the match indices for denoising
420
+ match_indices = self.get_dn_match_indices(dn_pos_idx, dn_num_group, batch["gt_groups"])
421
+
422
+ # Compute the denoising training loss
423
+ dn_loss = super().forward(dn_bboxes, dn_scores, batch, postfix="_dn", match_indices=match_indices)
424
+ total_loss.update(dn_loss)
425
+ else:
426
+ # If no denoising metadata is provided, set denoising loss to zero
427
+ total_loss.update({f"{k}_dn": torch.tensor(0.0, device=self.device) for k in total_loss.keys()})
428
+
429
+ return total_loss
430
+
431
+ @staticmethod
432
+ def get_dn_match_indices(dn_pos_idx, dn_num_group, gt_groups):
433
+ """
434
+ Get match indices for denoising.
435
+
436
+ Args:
437
+ dn_pos_idx (List[torch.Tensor]): List of tensors containing positive indices for denoising.
438
+ dn_num_group (int): Number of denoising groups.
439
+ gt_groups (List[int]): List of integers representing number of ground truths per image.
440
+
441
+ Returns:
442
+ (List[tuple]): List of tuples containing matched indices for denoising.
443
+ """
444
+ dn_match_indices = []
445
+ idx_groups = torch.as_tensor([0, *gt_groups[:-1]]).cumsum_(0)
446
+ for i, num_gt in enumerate(gt_groups):
447
+ if num_gt > 0:
448
+ gt_idx = torch.arange(end=num_gt, dtype=torch.long) + idx_groups[i]
449
+ gt_idx = gt_idx.repeat(dn_num_group)
450
+ assert len(dn_pos_idx[i]) == len(gt_idx), "Expected the same length, "
451
+ f"but got {len(dn_pos_idx[i])} and {len(gt_idx)} respectively."
452
+ dn_match_indices.append((dn_pos_idx[i], gt_idx))
453
+ else:
454
+ dn_match_indices.append((torch.zeros([0], dtype=torch.long), torch.zeros([0], dtype=torch.long)))
455
+ return dn_match_indices