dgenerate-ultralytics-headless 8.3.244__py3-none-any.whl → 8.3.246__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.244
3
+ Version: 8.3.246
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>
@@ -57,7 +57,7 @@ Provides-Extra: export
57
57
  Requires-Dist: numpy<2.0.0; extra == "export"
58
58
  Requires-Dist: onnx>=1.12.0; platform_system != "Darwin" and extra == "export"
59
59
  Requires-Dist: onnx<1.18.0,>=1.12.0; platform_system == "Darwin" and extra == "export"
60
- Requires-Dist: onnxslim>=0.1.80; extra == "export"
60
+ Requires-Dist: onnxslim>=0.1.82; extra == "export"
61
61
  Requires-Dist: coremltools>=9.0; (platform_system != "Windows" and python_version <= "3.13") and extra == "export"
62
62
  Requires-Dist: scikit-learn>=1.3.2; (platform_system != "Windows" and python_version <= "3.13") and extra == "export"
63
63
  Requires-Dist: openvino>=2024.0.0; extra == "export"
@@ -1,14 +1,14 @@
1
- dgenerate_ultralytics_headless-8.3.244.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
1
+ dgenerate_ultralytics_headless-8.3.246.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
2
2
  tests/__init__.py,sha256=bCox_hLdGRFYGLb2kd722VdNP2zEXNYNuLLYtqZSrbw,804
3
3
  tests/conftest.py,sha256=mOy9lGpNp7lk1hHl6_pVE0f9cU-72gnkoSm4TO-CNZU,2318
4
4
  tests/test_cli.py,sha256=GhIFHi-_WIJpDgoGNRi0DnjbfwP1wHbklBMnkCM-P_4,5464
5
5
  tests/test_cuda.py,sha256=eQew1rNwU3VViQCG6HZj5SWcYmWYop9gJ0jv9U1bGDE,8203
6
6
  tests/test_engine.py,sha256=0SWVHTs-feV07spjRMJ078Ipdg6m3uymNHwgTIZjZtc,5732
7
- tests/test_exports.py,sha256=UCLbjUnK8ZNldnJodrAxftUrwzO6ZNQxr7j64nDl9io,14137
7
+ tests/test_exports.py,sha256=5G5EgDmars6d-N7TVnJdDFWId0IJs-yw03DvdQIjrNU,14246
8
8
  tests/test_integrations.py,sha256=6QgSh9n0J04RdUYz08VeVOnKmf4S5MDEQ0chzS7jo_c,6220
9
9
  tests/test_python.py,sha256=viMvRajIbDZdm64hRRg9i8qZ1sU9frwB69e56mxwEXk,29266
10
10
  tests/test_solutions.py,sha256=CIaphpmOXgz9AE9xcm1RWODKrwGfZLCc84IggGXArNM,14122
11
- ultralytics/__init__.py,sha256=i2L4lPOKs4lnVhIGuDybG7FHkLU8zzTB6-2JVOEPMTM,1302
11
+ ultralytics/__init__.py,sha256=zA1SrrkUbY0pB0fq-YkFi-qyresnypQAzaAZ6bowhcE,1302
12
12
  ultralytics/py.typed,sha256=la67KBlbjXN-_-DfGNcdOcjYumVpKG_Tkw-8n5dnGB4,8
13
13
  ultralytics/assets/bus.jpg,sha256=wCAZxJecGR63Od3ZRERe9Aja1Weayrb9Ug751DS_vGM,137419
14
14
  ultralytics/assets/zidane.jpg,sha256=Ftc4aeMmen1O0A3o6GCDO9FlfBslLpTAw0gnetx7bts,50427
@@ -123,7 +123,7 @@ ultralytics/data/scripts/get_coco.sh,sha256=UuJpJeo3qQpTHVINeOpmP0NYmg8PhEFE3A8J
123
123
  ultralytics/data/scripts/get_coco128.sh,sha256=qmRQl_hOKrsdHrTrnyQuFIH01oDz3lfaz138OgGfLt8,650
124
124
  ultralytics/data/scripts/get_imagenet.sh,sha256=hr42H16bM47iT27rgS7MpEo-GeOZAYUQXgr0B2cwn48,1705
125
125
  ultralytics/engine/__init__.py,sha256=lm6MckFYCPTbqIoX7w0s_daxdjNeBeKW6DXppv1-QUM,70
126
- ultralytics/engine/exporter.py,sha256=f1F0okbFSlIZKVHuiV6lPJxktHzZT5dR9XTi2xYcst0,72589
126
+ ultralytics/engine/exporter.py,sha256=Ncf5GK5xAqSu0DH-6z5V53qZB7LstDJFTMF5a-7VQfs,72639
127
127
  ultralytics/engine/model.py,sha256=61ea1rB0wmL0CCaEr8p5gzneH0eL55OOMaTcFt8fR80,53079
128
128
  ultralytics/engine/predictor.py,sha256=neYmNDX27Vv3ggk9xqaKlH6XzB2vlFIghU5o7ZC0zFo,22838
129
129
  ultralytics/engine/results.py,sha256=LHX0AaVOv3CEjYjw8i4LThXqihxmahWCxpH20b4s9dM,68030
@@ -198,7 +198,7 @@ ultralytics/models/yolo/pose/predict.py,sha256=rsorTRpyL-x40R2QVDDG2isc1e2F2lGfD
198
198
  ultralytics/models/yolo/pose/train.py,sha256=lKxZ1dnkN3WlEPGlIlLF7ZuR_W2eoPrxhVrKGbJIQto,4628
199
199
  ultralytics/models/yolo/pose/val.py,sha256=s5WmXcZI5cAi3LPdIVHnkFUbEoFZsw5PBnnLnZ3Ep_c,12004
200
200
  ultralytics/models/yolo/segment/__init__.py,sha256=3IThhZ1wlkY9FvmWm9cE-5-ZyE6F1FgzAtQ6jOOFzzw,275
201
- ultralytics/models/yolo/segment/predict.py,sha256=fSGJVli-N84-jmqCCV4FDuQHyo7j1i0gPO7RsxTS9BM,5429
201
+ ultralytics/models/yolo/segment/predict.py,sha256=XK-SOrxfcIT8c52JC2ruEf3y9xcWSHsi6Yj1jZ0JqdU,5429
202
202
  ultralytics/models/yolo/segment/train.py,sha256=i1nDO0B7ScFo3G64ZSTmRZ2WLUVaMsvAoedSYa_MoIU,3009
203
203
  ultralytics/models/yolo/segment/val.py,sha256=LkyV5_I5YPdJNyI6OGy2i7J_r0Ll-jYdru_HXS1mN6s,13252
204
204
  ultralytics/models/yolo/world/__init__.py,sha256=nlh8I6t8hMGz_vZg8QSlsUW1R-2eKvn9CGUoPPQEGhA,131
@@ -217,9 +217,9 @@ ultralytics/nn/modules/__init__.py,sha256=5Sg_28MDfKwdu14Ty_WCaiIXZyjBSQ-xCNCwno
217
217
  ultralytics/nn/modules/activation.py,sha256=J6n-CJKFK0YbhwcRDqm9zEJM9pSAEycj5quQss_3x6E,2219
218
218
  ultralytics/nn/modules/block.py,sha256=YRALZHImSMdLpmF0qIf8uF3yENz0EK63SFp7gzylo5g,69885
219
219
  ultralytics/nn/modules/conv.py,sha256=9WUlBzHD-wLgz0riLyttzASLIqBtXPK6Jk5EdyIiGCM,21100
220
- ultralytics/nn/modules/head.py,sha256=OD8slnnJbVG9WvbRJqhx0tHwbtgrci3Ynj9dxHcszfY,51875
220
+ ultralytics/nn/modules/head.py,sha256=V1zSWN-AOHPkciqvfruDA0LgBgSGyKc_CULNCNEAe8o,51875
221
221
  ultralytics/nn/modules/transformer.py,sha256=oasUhhIm03kY0QtWrpvSSLnQa9q3eW2ksx82MgpPmsE,31972
222
- ultralytics/nn/modules/utils.py,sha256=tkUDhTXjmW-YMvTGvM4RFUVtzh5k2c33i3TWmzaWWtI,6067
222
+ ultralytics/nn/modules/utils.py,sha256=EyhENse_RESlXjLHAJWvV07_tq1MVMmfzXgPR1fiT9w,6066
223
223
  ultralytics/solutions/__init__.py,sha256=Jj7OcRiYjHH-e104H4xTgjjR5W6aPB4mBRndbaSPmgU,1209
224
224
  ultralytics/solutions/ai_gym.py,sha256=ItLE6HYMx6AEgiHEDG1HKDkippnrnycb-79S2g72AYA,5181
225
225
  ultralytics/solutions/analytics.py,sha256=UaH-B6h8Ir9l00deRUeAIW6QQTIO_595HTp93sdwteM,12820
@@ -254,7 +254,7 @@ ultralytics/utils/__init__.py,sha256=JfvODTB4mG_JOhTeCiPtq0iCEgiCh14hJf195rnOhLQ
254
254
  ultralytics/utils/autobatch.py,sha256=jiE4m_--H9UkXFDm_FqzcZk_hSTCGpS72XdVEKgZwAo,5114
255
255
  ultralytics/utils/autodevice.py,sha256=rXlPuo-iX-vZ4BabmMGEGh9Uxpau4R7Zlt1KCo9Xfyc,8892
256
256
  ultralytics/utils/benchmarks.py,sha256=S_W4S4pe2ktSRdSuWb6m09UEFQmZhmjl943bbo67hOI,32277
257
- ultralytics/utils/checks.py,sha256=9RGHIs4_heSFSL2YHRw0M3gLob6G9wQV3a24A0pTWrc,38411
257
+ ultralytics/utils/checks.py,sha256=LjcAbcpjo-WmLGbDYZk0vo8UQnzzLUewz7x8jkwjNN8,38534
258
258
  ultralytics/utils/cpu.py,sha256=OksKOlX93AsbSsFuoYvLXRXgpkOibrZSwQyW6lipt4Q,3493
259
259
  ultralytics/utils/dist.py,sha256=hOuY1-unhQAY-uWiZw3LWw36d1mqJuYK75NdlwB4oKE,4131
260
260
  ultralytics/utils/downloads.py,sha256=IyiGjjXqOyf1B0qLMk7vE6sSQ8s232OhKS8aj9XbTgs,22883
@@ -263,13 +263,13 @@ ultralytics/utils/events.py,sha256=6vqs_iSxoXIhQ804sOjApNZmXwNW9FUFtjaHPY8ta10,4
263
263
  ultralytics/utils/files.py,sha256=BdaRwEKqzle4glSj8n_jq6bDjTCAs_H1SN06ZOQ9qFU,8190
264
264
  ultralytics/utils/git.py,sha256=UdqeIiiEzg1qkerAZrg5YtTYPuJYwrpxW9N_6Pq6s8U,5501
265
265
  ultralytics/utils/instance.py,sha256=11mhefvTI9ftMqSirXuiViAi0Fxlo6v84qvNxfRNUoE,18862
266
- ultralytics/utils/logger.py,sha256=US4pLBmRQNI31KEeqqKdBEXDLS1eE5J5hWR0xPDaGJI,18966
266
+ ultralytics/utils/logger.py,sha256=LRhi4d76BYiHmSzjZv8V1TpNRpUoufJQYC1QQUOqhtw,19045
267
267
  ultralytics/utils/loss.py,sha256=t-z7qkvqF8OtuRHrj2wmvClZV2CCumIRi9jnqkc9i_A,39573
268
- ultralytics/utils/metrics.py,sha256=apVQLSML4TKwreFwRtWPQ1R5_fpp7vPDuI1q3cTY24w,68674
268
+ ultralytics/utils/metrics.py,sha256=sqqFPhqhAva30KU8i8OJB2Q-JwytCaZJVX99wpDH6gE,69197
269
269
  ultralytics/utils/nms.py,sha256=zv1rOzMF6WU8Kdk41VzNf1H1EMt_vZHcbDFbg3mnN2o,14248
270
- ultralytics/utils/ops.py,sha256=mbrqv36ovUp9FMIqClTHikOOViYEJ058CH-qDLkWbSw,25797
270
+ ultralytics/utils/ops.py,sha256=nWvTLJSBeW_XrxCy5Ytxl7sZJHp2sRqyCv4mm8QwYnw,25797
271
271
  ultralytics/utils/patches.py,sha256=mD3slAMAhcezzP42_fOWmacNMU6zXB68Br4_EBCyIjs,7117
272
- ultralytics/utils/plotting.py,sha256=nLProk2U3xYBwV4CdkeBx1mrPnrPA550cNSQRGbcLsg,48368
272
+ ultralytics/utils/plotting.py,sha256=NseUsSUKkeFDMEC_iJsnRXFs_G4Oem5RAyUqVIBw6Sg,48366
273
273
  ultralytics/utils/tal.py,sha256=w7oi6fp0NmL6hHh-yvCCX1cBuuB4JuX7w1wiR4_SMZs,20678
274
274
  ultralytics/utils/torch_utils.py,sha256=zOPUQlorTiEPSkqlSEPyaQhpmzmgOIKF7f3xJb0UjdQ,40268
275
275
  ultralytics/utils/tqdm.py,sha256=4kL_nczykHu6VxRzRSbvUSJknrCZydoS_ZegZkFXpsg,16197
@@ -283,7 +283,7 @@ ultralytics/utils/callbacks/dvc.py,sha256=YT0Sa5P8Huj8Fn9jM2P6MYzUY3PIVxsa5BInVi
283
283
  ultralytics/utils/callbacks/hub.py,sha256=fVLqqr3ZM6hoYFlVMEeejfq1MWDrkWCskPFOG3HGILQ,4159
284
284
  ultralytics/utils/callbacks/mlflow.py,sha256=wCXjQgdufp9LYujqMzLZOmIOur6kvrApHNeo9dA7t_g,5323
285
285
  ultralytics/utils/callbacks/neptune.py,sha256=_vt3cMwDHCR-LyT3KtRikGpj6AG11oQ-skUUUUdZ74o,4391
286
- ultralytics/utils/callbacks/platform.py,sha256=oWz8OvdgO3rCKe6VvqNOhwStS07ddJkvPy1O72SqYEc,9271
286
+ ultralytics/utils/callbacks/platform.py,sha256=_JpvGzhwb1gJLUOPKn7NSqt1I_RA11eKW6dhdjSifFA,10278
287
287
  ultralytics/utils/callbacks/raytune.py,sha256=Y0dFyNZVRuFovSh7nkgUIHTQL3xIXOACElgHuYbg_5I,1278
288
288
  ultralytics/utils/callbacks/tensorboard.py,sha256=PTJYvD2gqRUN8xw5VoTjvKnu2adukLfvhMlDgTnTiFU,4952
289
289
  ultralytics/utils/callbacks/wb.py,sha256=ghmL3gigOa-z_F54-TzMraKw9MAaYX-Wk4H8dLoRvX8,7705
@@ -291,8 +291,8 @@ ultralytics/utils/export/__init__.py,sha256=Cfh-PwVfTF_lwPp-Ss4wiX4z8Sm1XRPklsqd
291
291
  ultralytics/utils/export/engine.py,sha256=23-lC6dNsmz5vprSJzaN7UGNXrFlVedNcqhlOH_IXes,9956
292
292
  ultralytics/utils/export/imx.py,sha256=F3b334IZdwjF8PdP1s6QI3Ndd82_2e77clj8aGLzIDo,12856
293
293
  ultralytics/utils/export/tensorflow.py,sha256=igYzwbdblb9YgfV4Jgl5lMvynuVRcF51dAzI7j-BBI0,9966
294
- dgenerate_ultralytics_headless-8.3.244.dist-info/METADATA,sha256=lb4ts7ET4R5dsSjKMa0awTLNxVC2eyIb8YhP5Us8LUM,38799
295
- dgenerate_ultralytics_headless-8.3.244.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
296
- dgenerate_ultralytics_headless-8.3.244.dist-info/entry_points.txt,sha256=YM_wiKyTe9yRrsEfqvYolNO5ngwfoL4-NwgKzc8_7sI,93
297
- dgenerate_ultralytics_headless-8.3.244.dist-info/top_level.txt,sha256=XP49TwiMw4QGsvTLSYiJhz1xF_k7ev5mQ8jJXaXi45Q,12
298
- dgenerate_ultralytics_headless-8.3.244.dist-info/RECORD,,
294
+ dgenerate_ultralytics_headless-8.3.246.dist-info/METADATA,sha256=LoBmAU4Ur_f8FTLn5Ch-ebFhBwMFGA15N39d8IoNYIA,38799
295
+ dgenerate_ultralytics_headless-8.3.246.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
296
+ dgenerate_ultralytics_headless-8.3.246.dist-info/entry_points.txt,sha256=YM_wiKyTe9yRrsEfqvYolNO5ngwfoL4-NwgKzc8_7sI,93
297
+ dgenerate_ultralytics_headless-8.3.246.dist-info/top_level.txt,sha256=XP49TwiMw4QGsvTLSYiJhz1xF_k7ev5mQ8jJXaXi45Q,12
298
+ dgenerate_ultralytics_headless-8.3.246.dist-info/RECORD,,
tests/test_exports.py CHANGED
@@ -267,13 +267,13 @@ def test_export_imx():
267
267
  @pytest.mark.skipif(not checks.IS_PYTHON_3_10, reason="Axelera export requires Python 3.10")
268
268
  def test_export_axelera():
269
269
  """Test YOLO export to Axelera format."""
270
- # For faster testing, use a smaller calibration dataset
271
- # 32 image size crashes axelera export, so use 64
270
+ # For faster testing, use a smaller calibration dataset (32 image size crashes axelera export, so 64 is used)
272
271
  file = YOLO(MODEL).export(format="axelera", imgsz=64, data="coco8.yaml")
273
272
  assert Path(file).exists(), f"Axelera export failed, directory not found: {file}"
274
273
  shutil.rmtree(file, ignore_errors=True) # cleanup
275
274
 
276
275
 
276
+ # @pytest.mark.skipif(True, reason="Disabled for debugging ruamel.yaml installation required by executorch")
277
277
  @pytest.mark.skipif(not checks.IS_PYTHON_MINIMUM_3_10 or not TORCH_2_9, reason="Requires Python>=3.10 and Torch>=2.9.0")
278
278
  @pytest.mark.skipif(WINDOWS, reason="Skipping test on Windows")
279
279
  def test_export_executorch():
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.244"
3
+ __version__ = "8.3.246"
4
4
 
5
5
  import importlib
6
6
  import os
@@ -1192,6 +1192,8 @@ class Exporter:
1192
1192
  # BUG executorch build on arm64 Docker requires packaging>=22.0 https://github.com/pypa/setuptools/issues/4483
1193
1193
  if LINUX and ARM64 and IS_DOCKER:
1194
1194
  check_requirements("packaging>=22.0")
1195
+
1196
+ check_requirements("ruamel.yaml<0.19.0")
1195
1197
  check_requirements("executorch==1.0.1", "flatbuffers")
1196
1198
  # Pin numpy to avoid coremltools errors with numpy>=2.4.0, must be separate
1197
1199
  check_requirements("numpy<=2.3.5")
@@ -98,9 +98,9 @@ class SegmentationPredictor(DetectionPredictor):
98
98
  masks = None
99
99
  elif self.args.retina_masks:
100
100
  pred[:, :4] = ops.scale_boxes(img.shape[2:], pred[:, :4], orig_img.shape)
101
- masks = ops.process_mask_native(proto, pred[:, 6:], pred[:, :4], orig_img.shape[:2]) # HWC
101
+ masks = ops.process_mask_native(proto, pred[:, 6:], pred[:, :4], orig_img.shape[:2]) # NHW
102
102
  else:
103
- masks = ops.process_mask(proto, pred[:, 6:], pred[:, :4], img.shape[2:], upsample=True) # HWC
103
+ masks = ops.process_mask(proto, pred[:, 6:], pred[:, :4], img.shape[2:], upsample=True) # NHW
104
104
  pred[:, :4] = ops.scale_boxes(img.shape[2:], pred[:, :4], orig_img.shape)
105
105
  if masks is not None:
106
106
  keep = masks.amax((-2, -1)) > 0 # only keep predictions with masks
@@ -1078,9 +1078,9 @@ class RTDETRDecoder(nn.Module):
1078
1078
  enc_outputs_scores = self.enc_score_head(features) # (bs, h*w, nc)
1079
1079
 
1080
1080
  # Query selection
1081
- # (bs, num_queries)
1081
+ # (bs*num_queries,)
1082
1082
  topk_ind = torch.topk(enc_outputs_scores.max(-1).values, self.num_queries, dim=1).indices.view(-1)
1083
- # (bs, num_queries)
1083
+ # (bs*num_queries,)
1084
1084
  batch_ind = torch.arange(end=bs, dtype=topk_ind.dtype).unsqueeze(-1).repeat(1, self.num_queries).view(-1)
1085
1085
 
1086
1086
  # (bs, num_queries, 256)
@@ -147,7 +147,7 @@ def multi_scale_deformable_attn_pytorch(
147
147
  sampling_value_list.append(sampling_value_l_)
148
148
  # (bs, num_queries, num_heads, num_levels, num_points) ->
149
149
  # (bs, num_heads, num_queries, num_levels, num_points) ->
150
- # (bs, num_heads, 1, num_queries, num_levels*num_points)
150
+ # (bs*num_heads, 1, num_queries, num_levels*num_points)
151
151
  attention_weights = attention_weights.transpose(1, 2).reshape(
152
152
  bs * num_heads, 1, num_queries, num_levels * num_points
153
153
  )
@@ -90,11 +90,18 @@ def _upload_model_async(model_path, project, name):
90
90
 
91
91
  def _get_environment_info():
92
92
  """Collect comprehensive environment info using existing ultralytics utilities."""
93
+ import shutil
94
+
95
+ import psutil
93
96
  import torch
94
97
 
95
98
  from ultralytics import __version__
96
99
  from ultralytics.utils.torch_utils import get_cpu_info, get_gpu_info
97
100
 
101
+ # Get RAM and disk totals
102
+ memory = psutil.virtual_memory()
103
+ disk_usage = shutil.disk_usage("/")
104
+
98
105
  env = {
99
106
  "ultralyticsVersion": __version__,
100
107
  "hostname": socket.gethostname(),
@@ -105,6 +112,8 @@ def _get_environment_info():
105
112
  "cpuCount": os.cpu_count() or 0,
106
113
  "cpu": get_cpu_info(),
107
114
  "command": " ".join(sys.argv),
115
+ "totalRamGb": round(memory.total / (1 << 30), 1), # Total RAM in GB
116
+ "totalDiskGb": round(disk_usage.total / (1 << 30), 1), # Total disk in GB
108
117
  }
109
118
 
110
119
  # Git info using cached GIT singleton (no subprocess calls)
@@ -243,7 +252,7 @@ def on_model_save(trainer):
243
252
 
244
253
 
245
254
  def on_train_end(trainer):
246
- """Log final results and upload best model."""
255
+ """Log final results, upload best model, and send validation plot data."""
247
256
  global _console_logger
248
257
 
249
258
  if RANK not in {-1, 0} or not trainer.args.project:
@@ -251,17 +260,28 @@ def on_train_end(trainer):
251
260
 
252
261
  project, name = str(trainer.args.project), str(trainer.args.name or "train")
253
262
 
254
- # Stop console capture and flush remaining output
263
+ # Stop console capture
255
264
  if _console_logger:
256
265
  _console_logger.stop_capture()
257
266
  _console_logger = None
258
267
 
259
268
  # Upload best model (blocking to ensure it completes)
260
269
  model_path = None
270
+ model_size = None
261
271
  if trainer.best and Path(trainer.best).exists():
272
+ model_size = Path(trainer.best).stat().st_size
262
273
  model_path = _upload_model(trainer.best, project, name)
263
274
 
264
- # Send training complete
275
+ # Collect plots from trainer and validator
276
+ plots = [info["data"] for info in getattr(trainer, "plots", {}).values() if info.get("data")]
277
+ plots += [
278
+ info["data"] for info in getattr(getattr(trainer, "validator", None), "plots", {}).values() if info.get("data")
279
+ ]
280
+
281
+ # Get class names
282
+ names = getattr(getattr(trainer, "validator", None), "names", None) or (trainer.data or {}).get("names")
283
+ class_names = list(names.values()) if isinstance(names, dict) else list(names) if names else None
284
+
265
285
  _send(
266
286
  "training_complete",
267
287
  {
@@ -269,13 +289,16 @@ def on_train_end(trainer):
269
289
  "metrics": {**trainer.metrics, "fitness": trainer.fitness},
270
290
  "bestEpoch": getattr(trainer, "best_epoch", trainer.epoch),
271
291
  "bestFitness": trainer.best_fitness,
272
- "modelPath": model_path or str(trainer.best) if trainer.best else None,
273
- }
292
+ "modelPath": model_path or (str(trainer.best) if trainer.best else None),
293
+ "modelSize": model_size,
294
+ },
295
+ "classNames": class_names,
296
+ "plots": plots,
274
297
  },
275
298
  project,
276
299
  name,
277
300
  )
278
- LOGGER.info(f"Platform: Training complete, results uploaded to '{project}'")
301
+ LOGGER.info(f"Platform: Training complete, results uploaded to '{project}' ({len(plots)} plots)")
279
302
 
280
303
 
281
304
  callbacks = (
@@ -489,7 +489,10 @@ def check_requirements(requirements=ROOT.parent / "requirements.txt", exclude=()
489
489
  f"{prefix} {colorstr('bold', 'Restart runtime or rerun command for updates to take effect')}\n"
490
490
  )
491
491
  except Exception as e:
492
- LOGGER.warning(f"{prefix} ❌ {e}")
492
+ msg = f"{prefix} ❌ {e}"
493
+ if hasattr(e, "output") and e.output:
494
+ msg += f"\n{e.output}"
495
+ LOGGER.warning(msg)
493
496
  return False
494
497
  else:
495
498
  return False
@@ -8,7 +8,7 @@ import time
8
8
  from datetime import datetime
9
9
  from pathlib import Path
10
10
 
11
- from ultralytics.utils import MACOS, RANK
11
+ from ultralytics.utils import LOGGER, MACOS, RANK
12
12
  from ultralytics.utils.checks import check_requirements
13
13
 
14
14
 
@@ -336,7 +336,8 @@ class SystemLogger:
336
336
  self.pynvml = __import__("pynvml")
337
337
  self.pynvml.nvmlInit()
338
338
  return True
339
- except Exception:
339
+ except Exception as e:
340
+ LOGGER.warning(f"SystemLogger NVML init failed: {e}")
340
341
  return False
341
342
 
342
343
  def get_metrics(self, rates=False):
@@ -568,7 +568,8 @@ class ConfusionMatrix(DataExportMixin):
568
568
  fig.savefig(plot_fname, dpi=250)
569
569
  plt.close(fig)
570
570
  if on_plot:
571
- on_plot(plot_fname)
571
+ # Pass confusion matrix data for interactive plotting (raw counts only, normalization done on frontend)
572
+ on_plot(plot_fname, {"type": "confusion_matrix", "matrix": self.matrix.tolist()})
572
573
 
573
574
  def print(self):
574
575
  """Print the confusion matrix to the console."""
@@ -661,7 +662,8 @@ def plot_pr_curve(
661
662
  fig.savefig(save_dir, dpi=250)
662
663
  plt.close(fig)
663
664
  if on_plot:
664
- on_plot(save_dir)
665
+ # Pass PR curve data for interactive plotting (class names stored at model level)
666
+ on_plot(save_dir, {"type": "pr_curve", "x": px.tolist(), "y": py.tolist(), "ap": ap.tolist()})
665
667
 
666
668
 
667
669
  @plt_settings()
@@ -706,7 +708,8 @@ def plot_mc_curve(
706
708
  fig.savefig(save_dir, dpi=250)
707
709
  plt.close(fig)
708
710
  if on_plot:
709
- on_plot(save_dir)
711
+ # Pass metric-confidence curve data for interactive plotting (class names stored at model level)
712
+ on_plot(save_dir, {"type": f"{ylabel.lower()}_curve", "x": px.tolist(), "y": py.tolist()})
710
713
 
711
714
 
712
715
  def compute_ap(recall: list[float], precision: list[float]) -> tuple[float, np.ndarray, np.ndarray]:
ultralytics/utils/ops.py CHANGED
@@ -484,15 +484,15 @@ def process_mask(protos, masks_in, bboxes, shape, upsample: bool = False):
484
484
  are the height and width of the input image. The mask is applied to the bounding boxes.
485
485
  """
486
486
  c, mh, mw = protos.shape # CHW
487
- masks = (masks_in @ protos.float().view(c, -1)).view(-1, mh, mw) # CHW
487
+ masks = (masks_in @ protos.float().view(c, -1)).view(-1, mh, mw) # NHW
488
488
 
489
489
  width_ratio = mw / shape[1]
490
490
  height_ratio = mh / shape[0]
491
491
  ratios = torch.tensor([[width_ratio, height_ratio, width_ratio, height_ratio]], device=bboxes.device)
492
492
 
493
- masks = crop_mask(masks, boxes=bboxes * ratios) # CHW
493
+ masks = crop_mask(masks, boxes=bboxes * ratios) # NHW
494
494
  if upsample:
495
- masks = F.interpolate(masks[None], shape, mode="bilinear")[0] # CHW
495
+ masks = F.interpolate(masks[None], shape, mode="bilinear")[0] # NHW
496
496
  return masks.gt_(0.0).byte()
497
497
 
498
498
 
@@ -506,12 +506,12 @@ def process_mask_native(protos, masks_in, bboxes, shape):
506
506
  shape (tuple): Input image size as (height, width).
507
507
 
508
508
  Returns:
509
- (torch.Tensor): Binary mask tensor with shape (H, W, N).
509
+ (torch.Tensor): Binary mask tensor with shape (N, H, W).
510
510
  """
511
511
  c, mh, mw = protos.shape # CHW
512
512
  masks = (masks_in @ protos.float().view(c, -1)).view(-1, mh, mw)
513
- masks = scale_masks(masks[None], shape)[0] # CHW
514
- masks = crop_mask(masks, bboxes) # CHW
513
+ masks = scale_masks(masks[None], shape)[0] # NHW
514
+ masks = crop_mask(masks, bboxes) # NHW
515
515
  return masks.gt_(0.0).byte()
516
516
 
517
517
 
@@ -401,7 +401,7 @@ class Annotator:
401
401
  masks = masks.unsqueeze(3) # shape(n,h,w,1)
402
402
  masks_color = masks * (colors * alpha) # shape(n,h,w,3)
403
403
  inv_alpha_masks = (1 - masks * alpha).cumprod(0) # shape(n,h,w,1)
404
- mcs = masks_color.max(dim=0).values # shape(n,h,w,3)
404
+ mcs = masks_color.max(dim=0).values # shape(h,w,3)
405
405
 
406
406
  im_gpu = im_gpu.flip(dims=[0]).permute(1, 2, 0).contiguous() # shape(h,w,3)
407
407
  im_gpu = im_gpu * inv_alpha_masks[-1] + mcs