dgenerate-ultralytics-headless 8.3.175__py3-none-any.whl → 8.3.177__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dgenerate-ultralytics-headless
3
- Version: 8.3.175
3
+ Version: 8.3.177
4
4
  Summary: Automatically built Ultralytics package with python-opencv-headless dependency instead of python-opencv
5
5
  Author-email: Glenn Jocher <glenn.jocher@ultralytics.com>, Jing Qiu <jing.qiu@ultralytics.com>
6
6
  Maintainer-email: Ultralytics <hello@ultralytics.com>
@@ -1,14 +1,14 @@
1
- dgenerate_ultralytics_headless-8.3.175.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
1
+ dgenerate_ultralytics_headless-8.3.177.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
2
2
  tests/__init__.py,sha256=b4KP5_q-2IO8Br8YHOSLYnn7IwZS81l_vfEF2YPa2lM,894
3
3
  tests/conftest.py,sha256=LXtQJcFNWPGuzauTGkiXgsvVC3llJKfg22WcmhRzuQc,2593
4
4
  tests/test_cli.py,sha256=EMf5gTAopOnIz8VvzaM-Qb044o7D0flnUHYQ-2ffOM4,5670
5
5
  tests/test_cuda.py,sha256=-nQsfF3lGfqLm6cIeu_BCiXqLj7HzpL7R1GzPEc6z2I,8128
6
6
  tests/test_engine.py,sha256=Jpt2KVrltrEgh2-3Ykouz-2Z_2fza0eymL5ectRXadM,4922
7
- tests/test_exports.py,sha256=3JhxE6QxyYhwHugCr8CC1FQjTpeP5G72ACJ2twbgYrU,10331
7
+ tests/test_exports.py,sha256=CY-4xVZlVM16vdyIC0mSR3Ix59aiZm1qjFGIhSNmB20,11007
8
8
  tests/test_integrations.py,sha256=kl_AKmE_Qs1GB0_91iVwbzNxofm_hFTt0zzU6JF-pg4,6323
9
9
  tests/test_python.py,sha256=-qvdeg-hEcKU5mWSDEU24iFZ-i8FAwQRznSXpkp6WQ4,27928
10
10
  tests/test_solutions.py,sha256=tuf6n_fsI8KvSdJrnc-cqP2qYdiYqCWuVrx0z9dOz3Q,13213
11
- ultralytics/__init__.py,sha256=0fZl-D8kxXutIutI3XOSZ7JZa0PLd1AsYr2XyHM5Zwo,730
11
+ ultralytics/__init__.py,sha256=hBzrXExeyo-zxXKBW2PwzDCW5hndyDerj2NQCxQF5y4,730
12
12
  ultralytics/assets/bus.jpg,sha256=wCAZxJecGR63Od3ZRERe9Aja1Weayrb9Ug751DS_vGM,137419
13
13
  ultralytics/assets/zidane.jpg,sha256=Ftc4aeMmen1O0A3o6GCDO9FlfBslLpTAw0gnetx7bts,50427
14
14
  ultralytics/cfg/__init__.py,sha256=VIpPHImhjb0XLJquGZrG_LBGZchtOtBSXR7HYTYV2GU,39602
@@ -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=lrm1EF-P5fJQWiktTpihbQ5q1XGcAY1cPwmwAqdRioM,74920
123
+ ultralytics/engine/exporter.py,sha256=8H5FRyBNC6tpVMHk1iBXVyq9CLVA9rrkqY5lHT6-IR8,75068
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=QcHcbPVlLBiy_APwABr-T5K65HR8Bl1rRzxawjjP76E,71873
@@ -165,7 +165,7 @@ ultralytics/models/utils/__init__.py,sha256=lm6MckFYCPTbqIoX7w0s_daxdjNeBeKW6DXp
165
165
  ultralytics/models/utils/loss.py,sha256=E-61TfLPc04IdeL6IlFDityDoPju-ov0ouWV_cNY4Kg,21254
166
166
  ultralytics/models/utils/ops.py,sha256=Pr77n8XW25SUEx4X3bBvXcVIbRdJPoaXJuG0KWWawRQ,15253
167
167
  ultralytics/models/yolo/__init__.py,sha256=or0j5xvcM0usMlsFTYhNAOcQUri7reD0cD9JR5b7zDk,307
168
- ultralytics/models/yolo/model.py,sha256=50nGkmo7q9LMOBb6x15TSG2tt36wDhy02X6lH3TFDTc,18653
168
+ ultralytics/models/yolo/model.py,sha256=e66CIsSLHbEeGlkEQ1r6WwVDKAoR2nc0-UoGA94z-eM,18544
169
169
  ultralytics/models/yolo/classify/__init__.py,sha256=9--HVaNOfI1K7rn_rRqclL8FUAnpfeBrRqEQIaQw2xM,383
170
170
  ultralytics/models/yolo/classify/predict.py,sha256=FqAC2YXe25bRwedMZhF3Lw0waoY-a60xMKELhxApP9I,4149
171
171
  ultralytics/models/yolo/classify/train.py,sha256=V-hevc6X7xemnpyru84OfTRA77eNnkVSMEz16_OUvo4,10244
@@ -196,7 +196,7 @@ ultralytics/models/yolo/yoloe/train_seg.py,sha256=aCV7M8oQOvODFnU4piZdJh3tIrBJYA
196
196
  ultralytics/models/yolo/yoloe/val.py,sha256=yebPkxwKKt__cY05Zbh1YXg4_BKzzpcDc3Cv3FJ5SAA,9769
197
197
  ultralytics/nn/__init__.py,sha256=rjociYD9lo_K-d-1s6TbdWklPLjTcEHk7OIlRDJstIE,615
198
198
  ultralytics/nn/autobackend.py,sha256=wnIhA0tsgCn7berelnRvBRVLSV9Kz6ZPiryHavTkQNw,41789
199
- ultralytics/nn/tasks.py,sha256=jRUjYn1xz_LEa_zx6Upb0UpXvy0Bca1o5HEc7FCRgwM,72653
199
+ ultralytics/nn/tasks.py,sha256=vw_TNacAv-RN24rusFzKuYL6qRBD7cve8EpB7gOlU_8,72505
200
200
  ultralytics/nn/text_model.py,sha256=cYwD-0el4VeToDBP4iPFOQGqyEQatJOBHrVyONL3K_s,15282
201
201
  ultralytics/nn/modules/__init__.py,sha256=2nY0X69Z5DD5SWt6v3CUTZa5gXSzC9TQr3VTVqhyGho,3158
202
202
  ultralytics/nn/modules/activation.py,sha256=75JcIMH2Cu9GTC2Uf55r_5YLpxcrXQDaVoeGQ0hlUAU,2233
@@ -228,8 +228,8 @@ ultralytics/solutions/vision_eye.py,sha256=J_nsXhWkhfWz8THNJU4Yag4wbPv78ymby6SlN
228
228
  ultralytics/solutions/templates/similarity-search.html,sha256=nyyurpWlkvYlDeNh-74TlV4ctCpTksvkVy2Yc4ImQ1U,4261
229
229
  ultralytics/trackers/__init__.py,sha256=Zlu_Ig5osn7hqch_g5Be_e4pwZUkeeTQiesJCi0pFGI,255
230
230
  ultralytics/trackers/basetrack.py,sha256=-skBFFatzgJFAPN9Frm1u1h_RDUg3WOlxG6eHQxp2Gw,4384
231
- ultralytics/trackers/bot_sort.py,sha256=cogrHy5emkE5awrAt4WRuM9X_cnnuZNEICEZyBdjXd8,12130
232
- ultralytics/trackers/byte_tracker.py,sha256=E2ZZqGXbavG57Uh0LkF0S_SKR1FXv8Xd-1YJO1bH5ek,21768
231
+ ultralytics/trackers/bot_sort.py,sha256=o7FgI7hh5Ucfc5nUOrP1GKTbCetD4AWObL2wYVLJUvo,12247
232
+ ultralytics/trackers/byte_tracker.py,sha256=p8gSmdToCkNqN4so0rO7cTpTvKXAuuWWbjBt8UyT7_0,21506
233
233
  ultralytics/trackers/track.py,sha256=MHMydDt_MfXdj6naO2lLuEPF46pZUbDmz5Sqtr18-J4,4757
234
234
  ultralytics/trackers/utils/__init__.py,sha256=lm6MckFYCPTbqIoX7w0s_daxdjNeBeKW6DXppv1-QUM,70
235
235
  ultralytics/trackers/utils/gmc.py,sha256=9IvCf5MhBYY9ppVHykN02_oBWHmE98R8EaYFKaykdV0,14032
@@ -258,7 +258,7 @@ ultralytics/utils/tuner.py,sha256=bHr09Fz-0-t0ei55gX5wJh-obyiAQoicP7HUVM2I8qA,68
258
258
  ultralytics/utils/callbacks/__init__.py,sha256=hzL63Rce6VkZhP4Lcim9LKjadixaQG86nKqPhk7IkS0,242
259
259
  ultralytics/utils/callbacks/base.py,sha256=OJ6z4AYVCtXO-w6PSDRiwo1Tc2RYes-BzwKTsr9g_h0,6821
260
260
  ultralytics/utils/callbacks/clearml.py,sha256=xr5mZT_cY6AY_drbdCXFt-Dp2fOjRELxLDhDoRhNPg8,6067
261
- ultralytics/utils/callbacks/comet.py,sha256=VwIjpEqYDfcyvAMzBG1XAbcyy6lo45dNQRVlnO8VmSg,23924
261
+ ultralytics/utils/callbacks/comet.py,sha256=Ytv-dalpMBH36qsYIpU_VruREa9BVwFJzYDacZslEQU,25394
262
262
  ultralytics/utils/callbacks/dvc.py,sha256=NV0DXMQ1B5Sk5fmh60QFUGkifrAz-vwit5qhdfsyqXc,7511
263
263
  ultralytics/utils/callbacks/hub.py,sha256=1RmGiCaog1GoTya9OAyGELbQ2Lk5X3EWh7RYMxns0so,4177
264
264
  ultralytics/utils/callbacks/mlflow.py,sha256=6K8I5zij1yq3TUW9c5BBQNqdzz3IXugQjwKoBOvV6ag,5344
@@ -266,8 +266,8 @@ ultralytics/utils/callbacks/neptune.py,sha256=j8pecmlcsM8FGzLKWoBw5xUsi5t8E5HuxY
266
266
  ultralytics/utils/callbacks/raytune.py,sha256=S6Bq16oQDQ8BQgnZzA0zJHGN_BBr8iAM_WtGoLiEcwg,1283
267
267
  ultralytics/utils/callbacks/tensorboard.py,sha256=MDPBW7aDes-66OE6YqKXXvqA_EocjzEMHWGM-8z9vUQ,5281
268
268
  ultralytics/utils/callbacks/wb.py,sha256=Tm_-aRr2CN32MJkY9tylpMBJkb007-MSRNSQ7rDJ5QU,7521
269
- dgenerate_ultralytics_headless-8.3.175.dist-info/METADATA,sha256=_XCOeqAU-M0SVohm5hu97rfrYb7bC01C8WyrryxdK6Q,38716
270
- dgenerate_ultralytics_headless-8.3.175.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
271
- dgenerate_ultralytics_headless-8.3.175.dist-info/entry_points.txt,sha256=YM_wiKyTe9yRrsEfqvYolNO5ngwfoL4-NwgKzc8_7sI,93
272
- dgenerate_ultralytics_headless-8.3.175.dist-info/top_level.txt,sha256=XP49TwiMw4QGsvTLSYiJhz1xF_k7ev5mQ8jJXaXi45Q,12
273
- dgenerate_ultralytics_headless-8.3.175.dist-info/RECORD,,
269
+ dgenerate_ultralytics_headless-8.3.177.dist-info/METADATA,sha256=Ab4i3TVa7FICqy7bwVSdYFGNcqfu6Tg2QaOetQ1j7u0,38716
270
+ dgenerate_ultralytics_headless-8.3.177.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
271
+ dgenerate_ultralytics_headless-8.3.177.dist-info/entry_points.txt,sha256=YM_wiKyTe9yRrsEfqvYolNO5ngwfoL4-NwgKzc8_7sI,93
272
+ dgenerate_ultralytics_headless-8.3.177.dist-info/top_level.txt,sha256=XP49TwiMw4QGsvTLSYiJhz1xF_k7ev5mQ8jJXaXi45Q,12
273
+ dgenerate_ultralytics_headless-8.3.177.dist-info/RECORD,,
tests/test_exports.py CHANGED
@@ -100,7 +100,9 @@ def test_export_onnx_matrix(task, dynamic, int8, half, batch, simplify, nms):
100
100
  "task, dynamic, int8, half, batch, nms",
101
101
  [ # generate all combinations except for exclusion cases
102
102
  (task, dynamic, int8, half, batch, nms)
103
- for task, dynamic, int8, half, batch, nms in product(TASKS, [False], [False], [False], [1, 2], [True, False])
103
+ for task, dynamic, int8, half, batch, nms in product(
104
+ TASKS, [False, True], [False], [False], [1, 2], [True, False]
105
+ )
104
106
  if not (task == "classify" and nms)
105
107
  ],
106
108
  )
@@ -215,6 +217,22 @@ def test_export_mnn():
215
217
  YOLO(file)(SOURCE, imgsz=32) # exported model inference
216
218
 
217
219
 
220
+ @pytest.mark.slow
221
+ @pytest.mark.parametrize(
222
+ "task, int8, half, batch",
223
+ [ # generate all combinations except for exclusion cases
224
+ (task, int8, half, batch)
225
+ for task, int8, half, batch in product(TASKS, [True, False], [True, False], [1, 2])
226
+ if not (int8 and half)
227
+ ],
228
+ )
229
+ def test_export_mnn_matrix(task, int8, half, batch):
230
+ """Test YOLO export to MNN format considering various export configurations."""
231
+ file = YOLO(TASK2MODEL[task]).export(format="mnn", imgsz=32, int8=int8, half=half, batch=batch)
232
+ YOLO(file)([SOURCE] * batch, imgsz=32) # exported model inference
233
+ Path(file).unlink() # cleanup
234
+
235
+
218
236
  @pytest.mark.slow
219
237
  def test_export_ncnn():
220
238
  """Test YOLO export to NCNN format."""
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.175"
3
+ __version__ = "8.3.177"
4
4
 
5
5
  import os
6
6
 
@@ -115,7 +115,7 @@ def export_formats():
115
115
  """Return a dictionary of Ultralytics YOLO export formats."""
116
116
  x = [
117
117
  ["PyTorch", "-", ".pt", True, True, []],
118
- ["TorchScript", "torchscript", ".torchscript", True, True, ["batch", "optimize", "half", "nms"]],
118
+ ["TorchScript", "torchscript", ".torchscript", True, True, ["batch", "optimize", "half", "nms", "dynamic"]],
119
119
  ["ONNX", "onnx", ".onnx", True, True, ["batch", "dynamic", "half", "opset", "simplify", "nms"]],
120
120
  [
121
121
  "OpenVINO",
@@ -416,6 +416,8 @@ class Exporter:
416
416
  m.format = self.args.format
417
417
  m.max_det = self.args.max_det
418
418
  m.xyxy = self.args.nms and not coreml
419
+ if hasattr(model, "pe") and hasattr(m, "fuse"): # for YOLOE models
420
+ m.fuse(model.pe.to(self.device))
419
421
  elif isinstance(m, C2f) and not is_tf_format:
420
422
  # EdgeTPU does not support FlexSplitV while split provides cleaner ONNX graph
421
423
  m.forward = m.forward_split
@@ -324,7 +324,6 @@ class YOLOE(Model):
324
324
  embeddings (torch.Tensor): Embeddings corresponding to the classes.
325
325
  """
326
326
  assert isinstance(self.model, YOLOEModel)
327
- assert not self.is_fused(), "Model was fused during inference. set_classes() can no longer be used."
328
327
  self.model.set_classes(classes, embeddings)
329
328
  # Verify no background class is present
330
329
  assert " " not in classes
ultralytics/nn/tasks.py CHANGED
@@ -249,8 +249,6 @@ class BaseModel(torch.nn.Module):
249
249
  m.forward = m.forward_fuse
250
250
  if isinstance(m, v10Detect):
251
251
  m.fuse() # remove one2many head
252
- if isinstance(m, YOLOEDetect) and hasattr(self, "pe"):
253
- m.fuse(self.pe.to(next(self.model.parameters()).device))
254
252
  self.info(verbose=verbose)
255
253
 
256
254
  return self
@@ -210,17 +210,17 @@ class BOTSORT(BYTETracker):
210
210
  """Return an instance of KalmanFilterXYWH for predicting and updating object states in the tracking process."""
211
211
  return KalmanFilterXYWH()
212
212
 
213
- def init_track(
214
- self, dets: np.ndarray, scores: np.ndarray, cls: np.ndarray, img: Optional[np.ndarray] = None
215
- ) -> List[BOTrack]:
213
+ def init_track(self, results, img: Optional[np.ndarray] = None) -> List[BOTrack]:
216
214
  """Initialize object tracks using detection bounding boxes, scores, class labels, and optional ReID features."""
217
- if len(dets) == 0:
215
+ if len(results) == 0:
218
216
  return []
217
+ bboxes = results.xywhr if hasattr(results, "xywhr") else results.xywh
218
+ bboxes = np.concatenate([bboxes, np.arange(len(bboxes)).reshape(-1, 1)], axis=-1)
219
219
  if self.args.with_reid and self.encoder is not None:
220
- features_keep = self.encoder(img, dets)
221
- return [BOTrack(xywh, s, c, f) for (xywh, s, c, f) in zip(dets, scores, cls, features_keep)] # detections
220
+ features_keep = self.encoder(img, bboxes)
221
+ return [BOTrack(xywh, s, c, f) for (xywh, s, c, f) in zip(bboxes, results.conf, results.cls, features_keep)]
222
222
  else:
223
- return [BOTrack(xywh, s, c) for (xywh, s, c) in zip(dets, scores, cls)] # detections
223
+ return [BOTrack(xywh, s, c) for (xywh, s, c) in zip(bboxes, results.conf, results.cls)]
224
224
 
225
225
  def get_dists(self, tracks: List[BOTrack], detections: List[BOTrack]) -> np.ndarray:
226
226
  """Calculate distances between tracks and detections using IoU and optionally ReID embeddings."""
@@ -303,28 +303,19 @@ class BYTETracker:
303
303
  removed_stracks = []
304
304
 
305
305
  scores = results.conf
306
- bboxes = results.xywhr if hasattr(results, "xywhr") else results.xywh
307
- # Add index
308
- bboxes = np.concatenate([bboxes, np.arange(len(bboxes)).reshape(-1, 1)], axis=-1)
309
- cls = results.cls
310
-
311
306
  remain_inds = scores >= self.args.track_high_thresh
312
307
  inds_low = scores > self.args.track_low_thresh
313
308
  inds_high = scores < self.args.track_high_thresh
314
309
 
315
310
  inds_second = inds_low & inds_high
316
- dets_second = bboxes[inds_second]
317
- dets = bboxes[remain_inds]
318
- scores_keep = scores[remain_inds]
319
- scores_second = scores[inds_second]
320
- cls_keep = cls[remain_inds]
321
- cls_second = cls[inds_second]
311
+ results_second = results[inds_second]
312
+ results = results[remain_inds]
322
313
  feats_keep = feats_second = img
323
314
  if feats is not None and len(feats):
324
315
  feats_keep = feats[remain_inds]
325
316
  feats_second = feats[inds_second]
326
317
 
327
- detections = self.init_track(dets, scores_keep, cls_keep, feats_keep)
318
+ detections = self.init_track(results, feats_keep)
328
319
  # Add newly detected tracklets to tracked_stracks
329
320
  unconfirmed = []
330
321
  tracked_stracks = [] # type: List[STrack]
@@ -340,7 +331,7 @@ class BYTETracker:
340
331
  if hasattr(self, "gmc") and img is not None:
341
332
  # use try-except here to bypass errors from gmc module
342
333
  try:
343
- warp = self.gmc.apply(img, dets)
334
+ warp = self.gmc.apply(img, results.xyxy)
344
335
  except Exception:
345
336
  warp = np.eye(2, 3)
346
337
  STrack.multi_gmc(strack_pool, warp)
@@ -359,7 +350,7 @@ class BYTETracker:
359
350
  track.re_activate(det, self.frame_id, new_id=False)
360
351
  refind_stracks.append(track)
361
352
  # Step 3: Second association, with low score detection boxes association the untrack to the low score detections
362
- detections_second = self.init_track(dets_second, scores_second, cls_second, feats_second)
353
+ detections_second = self.init_track(results_second, feats_second)
363
354
  r_tracked_stracks = [strack_pool[i] for i in u_track if strack_pool[i].state == TrackState.Tracked]
364
355
  # TODO
365
356
  dists = matching.iou_distance(r_tracked_stracks, detections_second)
@@ -420,11 +411,13 @@ class BYTETracker:
420
411
  """Return a Kalman filter object for tracking bounding boxes using KalmanFilterXYAH."""
421
412
  return KalmanFilterXYAH()
422
413
 
423
- def init_track(
424
- self, dets: np.ndarray, scores: np.ndarray, cls: np.ndarray, img: Optional[np.ndarray] = None
425
- ) -> List[STrack]:
414
+ def init_track(self, results, img: Optional[np.ndarray] = None) -> List[STrack]:
426
415
  """Initialize object tracking with given detections, scores, and class labels using the STrack algorithm."""
427
- return [STrack(xywh, s, c) for (xywh, s, c) in zip(dets, scores, cls)] if len(dets) else [] # detections
416
+ if len(results) == 0:
417
+ return []
418
+ bboxes = results.xywhr if hasattr(results, "xywhr") else results.xywh
419
+ bboxes = np.concatenate([bboxes, np.arange(len(bboxes)).reshape(-1, 1)], axis=-1)
420
+ return [STrack(xywh, s, c) for (xywh, s, c) in zip(bboxes, results.conf, results.cls)]
428
421
 
429
422
  def get_dists(self, tracks: List[STrack], detections: List[STrack]) -> np.ndarray:
430
423
  """Calculate the distance between tracks and detections using IoU and optionally fuse scores."""
@@ -26,9 +26,12 @@ try:
26
26
  # Names of plots created by Ultralytics that are logged to Comet
27
27
  CONFUSION_MATRIX_PLOT_NAMES = "confusion_matrix", "confusion_matrix_normalized"
28
28
  EVALUATION_PLOT_NAMES = "F1_curve", "P_curve", "R_curve", "PR_curve"
29
- LABEL_PLOT_NAMES = "labels", "labels_correlogram"
29
+ LABEL_PLOT_NAMES = ["labels"]
30
30
  SEGMENT_METRICS_PLOT_PREFIX = "Box", "Mask"
31
31
  POSE_METRICS_PLOT_PREFIX = "Box", "Pose"
32
+ DETECTION_METRICS_PLOT_PREFIX = ["Box"]
33
+ RESULTS_TABLE_NAME = "results.csv"
34
+ ARGS_YAML_NAME = "args.yaml"
32
35
 
33
36
  _comet_image_prediction_count = 0
34
37
 
@@ -353,7 +356,7 @@ def _log_confusion_matrix(experiment, trainer, curr_step, curr_epoch) -> None:
353
356
  )
354
357
 
355
358
 
356
- def _log_images(experiment, image_paths, curr_step, annotations=None) -> None:
359
+ def _log_images(experiment, image_paths, curr_step: Optional[int], annotations=None) -> None:
357
360
  """
358
361
  Log images to the experiment with optional annotations.
359
362
 
@@ -361,7 +364,7 @@ def _log_images(experiment, image_paths, curr_step, annotations=None) -> None:
361
364
  such as bounding boxes or segmentation masks.
362
365
 
363
366
  Args:
364
- experiment (comet_ml.Experiment): The Comet ML experiment to log images to.
367
+ experiment (comet_ml.CometExperiment): The Comet ML experiment to log images to.
365
368
  image_paths (List[Path]): List of paths to images that will be logged.
366
369
  curr_step (int): Current training step/iteration for tracking in the experiment timeline.
367
370
  annotations (List[List[dict]], optional): Nested list of annotation dictionaries for each image. Each
@@ -385,7 +388,7 @@ def _log_image_predictions(experiment, validator, curr_step) -> None:
385
388
  dashboard. The function respects configured limits on the number of images to log.
386
389
 
387
390
  Args:
388
- experiment (comet_ml.Experiment): The Comet ML experiment to log to.
391
+ experiment (comet_ml.CometExperiment): The Comet ML experiment to log to.
389
392
  validator (BaseValidator): The validator instance containing validation data and predictions.
390
393
  curr_step (int): The current training step for logging timeline.
391
394
 
@@ -448,7 +451,7 @@ def _log_plots(experiment, trainer) -> None:
448
451
  for each type.
449
452
 
450
453
  Args:
451
- experiment (comet_ml.Experiment): The Comet ML experiment to log plots to.
454
+ experiment (comet_ml.CometExperiment): The Comet ML experiment to log plots to.
452
455
  trainer (ultralytics.engine.trainer.BaseTrainer): The trainer object containing validation metrics and save
453
456
  directory information.
454
457
 
@@ -470,7 +473,11 @@ def _log_plots(experiment, trainer) -> None:
470
473
  for prefix in POSE_METRICS_PLOT_PREFIX
471
474
  ]
472
475
  elif isinstance(trainer.validator.metrics, (DetMetrics, OBBMetrics)):
473
- plot_filenames = [trainer.save_dir / f"{plots}.png" for plots in EVALUATION_PLOT_NAMES]
476
+ plot_filenames = [
477
+ trainer.save_dir / f"{prefix}{plots}.png"
478
+ for plots in EVALUATION_PLOT_NAMES
479
+ for prefix in DETECTION_METRICS_PLOT_PREFIX
480
+ ]
474
481
 
475
482
  if plot_filenames is not None:
476
483
  _log_images(experiment, plot_filenames, None)
@@ -495,6 +502,34 @@ def _log_image_batches(experiment, trainer, curr_step: int) -> None:
495
502
  _log_images(experiment, trainer.save_dir.glob("val_batch*.jpg"), curr_step)
496
503
 
497
504
 
505
+ def _log_asset(experiment, asset_path) -> None:
506
+ """
507
+ Logs a specific asset file to the given experiment.
508
+
509
+ This function facilitates logging an asset, such as a file, to the provided
510
+ experiment. It enables integration with experiment tracking platforms.
511
+
512
+ Args:
513
+ experiment (comet_ml.CometExperiment): The experiment instance to which the asset will be logged.
514
+ asset_path (Path): The file path of the asset to log.
515
+ """
516
+ experiment.log_asset(asset_path)
517
+
518
+
519
+ def _log_table(experiment, table_path) -> None:
520
+ """
521
+ Logs a table to the provided experiment.
522
+
523
+ This function is used to log a table file to the given experiment. The table
524
+ is identified by its file path.
525
+
526
+ Args:
527
+ experiment (comet_ml.CometExperiment): The experiment object where the table file will be logged.
528
+ table_path (Path): The file path of the table to be logged.
529
+ """
530
+ experiment.log_table(str(table_path))
531
+
532
+
498
533
  def on_pretrain_routine_start(trainer) -> None:
499
534
  """Create or resume a CometML experiment at the start of a YOLO pre-training routine."""
500
535
  _resume_or_create_experiment(trainer.args)
@@ -576,6 +611,16 @@ def on_train_end(trainer) -> None:
576
611
  _log_confusion_matrix(experiment, trainer, curr_step, curr_epoch)
577
612
  _log_image_predictions(experiment, trainer.validator, curr_step)
578
613
  _log_image_batches(experiment, trainer, curr_step)
614
+ # log results table
615
+ table_path = trainer.save_dir / RESULTS_TABLE_NAME
616
+ if table_path.exists():
617
+ _log_table(experiment, table_path)
618
+
619
+ # log arguments YAML
620
+ args_path = trainer.save_dir / ARGS_YAML_NAME
621
+ if args_path.exists():
622
+ _log_asset(experiment, args_path)
623
+
579
624
  experiment.end()
580
625
 
581
626
  global _comet_image_prediction_count