ultralytics 8.3.138__py3-none-any.whl → 8.3.140__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.
- tests/test_cuda.py +3 -2
- tests/test_python.py +9 -2
- tests/test_solutions.py +4 -5
- ultralytics/__init__.py +1 -1
- ultralytics/engine/exporter.py +1 -0
- ultralytics/engine/results.py +2 -209
- ultralytics/utils/__init__.py +153 -0
- ultralytics/utils/benchmarks.py +1 -0
- ultralytics/utils/checks.py +20 -6
- ultralytics/utils/metrics.py +90 -5
- {ultralytics-8.3.138.dist-info → ultralytics-8.3.140.dist-info}/METADATA +1 -1
- {ultralytics-8.3.138.dist-info → ultralytics-8.3.140.dist-info}/RECORD +16 -16
- {ultralytics-8.3.138.dist-info → ultralytics-8.3.140.dist-info}/WHEEL +0 -0
- {ultralytics-8.3.138.dist-info → ultralytics-8.3.140.dist-info}/entry_points.txt +0 -0
- {ultralytics-8.3.138.dist-info → ultralytics-8.3.140.dist-info}/licenses/LICENSE +0 -0
- {ultralytics-8.3.138.dist-info → ultralytics-8.3.140.dist-info}/top_level.txt +0 -0
tests/test_cuda.py
CHANGED
@@ -41,7 +41,6 @@ def test_amp():
|
|
41
41
|
|
42
42
|
|
43
43
|
@pytest.mark.slow
|
44
|
-
@pytest.mark.skipif(IS_JETSON, reason="Temporary disable ONNX for Jetson")
|
45
44
|
@pytest.mark.skipif(not DEVICES, reason="No CUDA devices available")
|
46
45
|
@pytest.mark.parametrize(
|
47
46
|
"task, dynamic, int8, half, batch, simplify, nms",
|
@@ -50,7 +49,9 @@ def test_amp():
|
|
50
49
|
for task, dynamic, int8, half, batch, simplify, nms in product(
|
51
50
|
TASKS, [True, False], [False], [False], [1, 2], [True, False], [True, False]
|
52
51
|
)
|
53
|
-
if not (
|
52
|
+
if not (
|
53
|
+
(int8 and half) or (task == "classify" and nms) or (task == "obb" and nms and (not TORCH_1_13 or IS_JETSON))
|
54
|
+
)
|
54
55
|
],
|
55
56
|
)
|
56
57
|
def test_export_onnx_matrix(task, dynamic, int8, half, batch, simplify, nms):
|
tests/test_python.py
CHANGED
@@ -198,7 +198,13 @@ def test_track_stream():
|
|
198
198
|
|
199
199
|
def test_val():
|
200
200
|
"""Test the validation mode of the YOLO model."""
|
201
|
-
YOLO(MODEL).val(data="coco8.yaml", imgsz=32)
|
201
|
+
metrics = YOLO(MODEL).val(data="coco8.yaml", imgsz=32)
|
202
|
+
metrics.to_df()
|
203
|
+
metrics.to_csv()
|
204
|
+
metrics.to_xml()
|
205
|
+
metrics.to_html()
|
206
|
+
metrics.to_json()
|
207
|
+
metrics.to_sql()
|
202
208
|
|
203
209
|
|
204
210
|
def test_train_scratch():
|
@@ -264,7 +270,8 @@ def test_predict_callback_and_setup():
|
|
264
270
|
@pytest.mark.parametrize("model", MODELS)
|
265
271
|
def test_results(model):
|
266
272
|
"""Test YOLO model results processing and output in various formats."""
|
267
|
-
|
273
|
+
temp_s = "https://ultralytics.com/images/boats.jpg" if model == "yolo11n-obb.pt" else SOURCE
|
274
|
+
results = YOLO(WEIGHTS_DIR / model)([temp_s, temp_s], imgsz=160)
|
268
275
|
for r in results:
|
269
276
|
r = r.cpu().numpy()
|
270
277
|
print(r, len(r), r.path) # print numpy attributes
|
tests/test_solutions.py
CHANGED
@@ -12,7 +12,7 @@ import pytest
|
|
12
12
|
|
13
13
|
from tests import MODEL, TMP
|
14
14
|
from ultralytics import solutions
|
15
|
-
from ultralytics.utils import ASSETS_URL, IS_RASPBERRYPI,
|
15
|
+
from ultralytics.utils import ASSETS_URL, IS_RASPBERRYPI, checks
|
16
16
|
from ultralytics.utils.downloads import safe_download
|
17
17
|
|
18
18
|
# Pre-defined arguments values
|
@@ -180,10 +180,7 @@ def process_video(solution, video_path, needs_frame_count=False):
|
|
180
180
|
cap.release()
|
181
181
|
|
182
182
|
|
183
|
-
@pytest.mark.skipif(
|
184
|
-
(LINUX and checks.IS_PYTHON_3_11) or IS_RASPBERRYPI,
|
185
|
-
reason="Disabled for testing due to --slow test errors after YOLOE PR.",
|
186
|
-
)
|
183
|
+
@pytest.mark.skipif(IS_RASPBERRYPI, reason="Disabled for testing due to --slow test errors after YOLOE PR.")
|
187
184
|
@pytest.mark.parametrize("name, solution_class, needs_frame_count, video, kwargs", SOLUTIONS)
|
188
185
|
def test_solution(name, solution_class, needs_frame_count, video, kwargs):
|
189
186
|
"""Test individual Ultralytics solution."""
|
@@ -300,6 +297,7 @@ def test_streamlit_handle_video_upload_creates_file():
|
|
300
297
|
os.remove("ultralytics.mp4")
|
301
298
|
|
302
299
|
|
300
|
+
@pytest.mark.skipif(IS_RASPBERRYPI, reason="Disabled due to slow performance on Raspberry Pi.")
|
303
301
|
def test_similarity_search_app_init():
|
304
302
|
"""Test SearchApp initializes with required attributes."""
|
305
303
|
app = solutions.SearchApp(device="cpu")
|
@@ -307,6 +305,7 @@ def test_similarity_search_app_init():
|
|
307
305
|
assert hasattr(app, "run")
|
308
306
|
|
309
307
|
|
308
|
+
@pytest.mark.skipif(IS_RASPBERRYPI, reason="Disabled due to slow performance on Raspberry Pi.")
|
310
309
|
def test_similarity_search_complete(tmp_path):
|
311
310
|
"""Test VisualAISearch end-to-end with sample image and query."""
|
312
311
|
from PIL import Image
|
ultralytics/__init__.py
CHANGED
ultralytics/engine/exporter.py
CHANGED
@@ -981,6 +981,7 @@ class Exporter:
|
|
981
981
|
custom_input_op_name_np_data_path=np_data,
|
982
982
|
enable_batchmatmul_unfold=True, # fix lower no. of detected objects on GPU delegate
|
983
983
|
output_signaturedefs=True, # fix error with Attention block group convolution
|
984
|
+
disable_group_convolution=self.args.format == "tfjs", # fix TF.js error with group convolution
|
984
985
|
optimization_for_gpu_delegate=True,
|
985
986
|
)
|
986
987
|
YAML.save(f / "metadata.yaml", self.metadata) # add metadata.yaml
|
ultralytics/engine/results.py
CHANGED
@@ -13,8 +13,7 @@ import numpy as np
|
|
13
13
|
import torch
|
14
14
|
|
15
15
|
from ultralytics.data.augment import LetterBox
|
16
|
-
from ultralytics.utils import LOGGER, SimpleClass, ops
|
17
|
-
from ultralytics.utils.checks import check_requirements
|
16
|
+
from ultralytics.utils import LOGGER, DataExportMixin, SimpleClass, ops
|
18
17
|
from ultralytics.utils.plotting import Annotator, colors, save_one_box
|
19
18
|
from ultralytics.utils.torch_utils import smart_inference_mode
|
20
19
|
|
@@ -184,7 +183,7 @@ class BaseTensor(SimpleClass):
|
|
184
183
|
return self.__class__(self.data[idx], self.orig_shape)
|
185
184
|
|
186
185
|
|
187
|
-
class Results(SimpleClass):
|
186
|
+
class Results(SimpleClass, DataExportMixin):
|
188
187
|
"""
|
189
188
|
A class for storing and manipulating inference results.
|
190
189
|
|
@@ -828,212 +827,6 @@ class Results(SimpleClass):
|
|
828
827
|
|
829
828
|
return results
|
830
829
|
|
831
|
-
def to_df(self, normalize=False, decimals=5):
|
832
|
-
"""
|
833
|
-
Converts detection results to a Pandas Dataframe.
|
834
|
-
|
835
|
-
This method converts the detection results into Pandas Dataframe format. It includes information
|
836
|
-
about detected objects such as bounding boxes, class names, confidence scores, and optionally
|
837
|
-
segmentation masks and keypoints.
|
838
|
-
|
839
|
-
Args:
|
840
|
-
normalize (bool): Whether to normalize the bounding box coordinates by the image dimensions.
|
841
|
-
If True, coordinates will be returned as float values between 0 and 1.
|
842
|
-
decimals (int): Number of decimal places to round the output values to.
|
843
|
-
|
844
|
-
Returns:
|
845
|
-
(DataFrame): A Pandas Dataframe containing all the information in results in an organized way.
|
846
|
-
|
847
|
-
Examples:
|
848
|
-
>>> results = model("path/to/image.jpg")
|
849
|
-
>>> for result in results:
|
850
|
-
>>> df_result = result.to_df()
|
851
|
-
>>> print(df_result)
|
852
|
-
"""
|
853
|
-
import pandas as pd # scope for faster 'import ultralytics'
|
854
|
-
|
855
|
-
return pd.DataFrame(self.summary(normalize=normalize, decimals=decimals))
|
856
|
-
|
857
|
-
def to_csv(self, normalize=False, decimals=5, *args, **kwargs):
|
858
|
-
"""
|
859
|
-
Converts detection results to a CSV format.
|
860
|
-
|
861
|
-
This method serializes the detection results into a CSV format. It includes information
|
862
|
-
about detected objects such as bounding boxes, class names, confidence scores, and optionally
|
863
|
-
segmentation masks and keypoints.
|
864
|
-
|
865
|
-
Args:
|
866
|
-
normalize (bool): Whether to normalize the bounding box coordinates by the image dimensions.
|
867
|
-
If True, coordinates will be returned as float values between 0 and 1.
|
868
|
-
decimals (int): Number of decimal places to round the output values to.
|
869
|
-
*args (Any): Variable length argument list to be passed to pandas.DataFrame.to_csv().
|
870
|
-
**kwargs (Any): Arbitrary keyword arguments to be passed to pandas.DataFrame.to_csv().
|
871
|
-
|
872
|
-
|
873
|
-
Returns:
|
874
|
-
(str): CSV containing all the information in results in an organized way.
|
875
|
-
|
876
|
-
Examples:
|
877
|
-
>>> results = model("path/to/image.jpg")
|
878
|
-
>>> for result in results:
|
879
|
-
>>> csv_result = result.to_csv()
|
880
|
-
>>> print(csv_result)
|
881
|
-
"""
|
882
|
-
return self.to_df(normalize=normalize, decimals=decimals).to_csv(*args, **kwargs)
|
883
|
-
|
884
|
-
def to_xml(self, normalize=False, decimals=5, *args, **kwargs):
|
885
|
-
"""
|
886
|
-
Converts detection results to XML format.
|
887
|
-
|
888
|
-
This method serializes the detection results into an XML format. It includes information
|
889
|
-
about detected objects such as bounding boxes, class names, confidence scores, and optionally
|
890
|
-
segmentation masks and keypoints.
|
891
|
-
|
892
|
-
Args:
|
893
|
-
normalize (bool): Whether to normalize the bounding box coordinates by the image dimensions.
|
894
|
-
If True, coordinates will be returned as float values between 0 and 1.
|
895
|
-
decimals (int): Number of decimal places to round the output values to.
|
896
|
-
*args (Any): Variable length argument list to be passed to pandas.DataFrame.to_xml().
|
897
|
-
**kwargs (Any): Arbitrary keyword arguments to be passed to pandas.DataFrame.to_xml().
|
898
|
-
|
899
|
-
Returns:
|
900
|
-
(str): An XML string containing all the information in results in an organized way.
|
901
|
-
|
902
|
-
Examples:
|
903
|
-
>>> results = model("path/to/image.jpg")
|
904
|
-
>>> for result in results:
|
905
|
-
>>> xml_result = result.to_xml()
|
906
|
-
>>> print(xml_result)
|
907
|
-
"""
|
908
|
-
check_requirements("lxml")
|
909
|
-
df = self.to_df(normalize=normalize, decimals=decimals)
|
910
|
-
return '<?xml version="1.0" encoding="utf-8"?>\n<root></root>' if df.empty else df.to_xml(*args, **kwargs)
|
911
|
-
|
912
|
-
def to_html(self, normalize=False, decimals=5, index=False, *args, **kwargs):
|
913
|
-
"""
|
914
|
-
Converts detection results to HTML format.
|
915
|
-
|
916
|
-
This method serializes the detection results into an HTML format. It includes information
|
917
|
-
about detected objects such as bounding boxes, class names, confidence scores, and optionally
|
918
|
-
segmentation masks and keypoints.
|
919
|
-
|
920
|
-
Args:
|
921
|
-
normalize (bool): Whether to normalize the bounding box coordinates by the image dimensions.
|
922
|
-
If True, coordinates will be returned as float values between 0 and 1.
|
923
|
-
decimals (int): Number of decimal places to round the output values to.
|
924
|
-
index (bool): Whether to include the DataFrame index in the HTML output.
|
925
|
-
*args (Any): Variable length argument list to be passed to pandas.DataFrame.to_html().
|
926
|
-
**kwargs (Any): Arbitrary keyword arguments to be passed to pandas.DataFrame.to_html().
|
927
|
-
|
928
|
-
Returns:
|
929
|
-
(str): An HTML string containing all the information in results in an organized way.
|
930
|
-
|
931
|
-
Examples:
|
932
|
-
>>> results = model("path/to/image.jpg")
|
933
|
-
>>> for result in results:
|
934
|
-
>>> html_result = result.to_html()
|
935
|
-
>>> print(html_result)
|
936
|
-
"""
|
937
|
-
df = self.to_df(normalize=normalize, decimals=decimals)
|
938
|
-
return "<table></table>" if df.empty else df.to_html(index=index, *args, **kwargs)
|
939
|
-
|
940
|
-
def tojson(self, normalize=False, decimals=5):
|
941
|
-
"""Deprecated version of to_json()."""
|
942
|
-
LOGGER.warning("'result.tojson()' is deprecated, replace with 'result.to_json()'.")
|
943
|
-
return self.to_json(normalize, decimals)
|
944
|
-
|
945
|
-
def to_json(self, normalize=False, decimals=5):
|
946
|
-
"""
|
947
|
-
Converts detection results to JSON format.
|
948
|
-
|
949
|
-
This method serializes the detection results into a JSON-compatible format. It includes information
|
950
|
-
about detected objects such as bounding boxes, class names, confidence scores, and optionally
|
951
|
-
segmentation masks and keypoints.
|
952
|
-
|
953
|
-
Args:
|
954
|
-
normalize (bool): Whether to normalize the bounding box coordinates by the image dimensions.
|
955
|
-
If True, coordinates will be returned as float values between 0 and 1.
|
956
|
-
decimals (int): Number of decimal places to round the output values to.
|
957
|
-
|
958
|
-
Returns:
|
959
|
-
(str): A JSON string containing the serialized detection results.
|
960
|
-
|
961
|
-
Examples:
|
962
|
-
>>> results = model("path/to/image.jpg")
|
963
|
-
>>> for result in results:
|
964
|
-
>>> json_result = result.to_json()
|
965
|
-
>>> print(json_result)
|
966
|
-
|
967
|
-
Notes:
|
968
|
-
- For classification tasks, the JSON will contain class probabilities instead of bounding boxes.
|
969
|
-
- For object detection tasks, the JSON will include bounding box coordinates, class names, and
|
970
|
-
confidence scores.
|
971
|
-
- If available, segmentation masks and keypoints will also be included in the JSON output.
|
972
|
-
- The method uses the `summary` method internally to generate the data structure before
|
973
|
-
converting it to JSON.
|
974
|
-
"""
|
975
|
-
import json
|
976
|
-
|
977
|
-
return json.dumps(self.summary(normalize=normalize, decimals=decimals), indent=2)
|
978
|
-
|
979
|
-
def to_sql(self, table_name="results", normalize=False, decimals=5, db_path="results.db"):
|
980
|
-
"""
|
981
|
-
Converts detection results to an SQL-compatible format.
|
982
|
-
|
983
|
-
This method serializes the detection results into a format compatible with SQL databases.
|
984
|
-
It includes information about detected objects such as bounding boxes, class names, confidence scores,
|
985
|
-
and optionally segmentation masks, keypoints or oriented bounding boxes.
|
986
|
-
|
987
|
-
Args:
|
988
|
-
table_name (str): Name of the SQL table where the data will be inserted.
|
989
|
-
normalize (bool): Whether to normalize the bounding box coordinates by the image dimensions.
|
990
|
-
If True, coordinates will be returned as float values between 0 and 1.
|
991
|
-
decimals (int): Number of decimal places to round the bounding boxes values to.
|
992
|
-
db_path (str): Path to the SQLite database file.
|
993
|
-
|
994
|
-
Examples:
|
995
|
-
>>> results = model("path/to/image.jpg")
|
996
|
-
>>> for result in results:
|
997
|
-
>>> result.to_sql()
|
998
|
-
"""
|
999
|
-
import json
|
1000
|
-
import sqlite3
|
1001
|
-
|
1002
|
-
# Convert results to a list of dictionaries
|
1003
|
-
data = self.summary(normalize=normalize, decimals=decimals)
|
1004
|
-
if len(data) == 0:
|
1005
|
-
LOGGER.warning("No results to save to SQL. Results dict is empty.")
|
1006
|
-
return
|
1007
|
-
|
1008
|
-
# Connect to the SQLite database
|
1009
|
-
conn = sqlite3.connect(db_path)
|
1010
|
-
cursor = conn.cursor()
|
1011
|
-
|
1012
|
-
# Create table if it doesn't exist
|
1013
|
-
columns = (
|
1014
|
-
"id INTEGER PRIMARY KEY AUTOINCREMENT, class_name TEXT, confidence REAL, box TEXT, masks TEXT, kpts TEXT"
|
1015
|
-
)
|
1016
|
-
cursor.execute(f"CREATE TABLE IF NOT EXISTS {table_name} ({columns})")
|
1017
|
-
|
1018
|
-
# Insert data into the table
|
1019
|
-
for item in data:
|
1020
|
-
cursor.execute(
|
1021
|
-
f"INSERT INTO {table_name} (class_name, confidence, box, masks, kpts) VALUES (?, ?, ?, ?, ?)",
|
1022
|
-
(
|
1023
|
-
item.get("name"),
|
1024
|
-
item.get("confidence"),
|
1025
|
-
json.dumps(item.get("box", {})),
|
1026
|
-
json.dumps(item.get("segments", {})),
|
1027
|
-
json.dumps(item.get("keypoints", {})),
|
1028
|
-
),
|
1029
|
-
)
|
1030
|
-
|
1031
|
-
# Commit and close the connection
|
1032
|
-
conn.commit()
|
1033
|
-
conn.close()
|
1034
|
-
|
1035
|
-
LOGGER.info(f"Detection results successfully written to SQL table '{table_name}' in database '{db_path}'.")
|
1036
|
-
|
1037
830
|
|
1038
831
|
class Boxes(BaseTensor):
|
1039
832
|
"""
|
ultralytics/utils/__init__.py
CHANGED
@@ -187,6 +187,159 @@ class TQDM(rich.tqdm if TQDM_RICH else tqdm.tqdm):
|
|
187
187
|
return super().__iter__()
|
188
188
|
|
189
189
|
|
190
|
+
class DataExportMixin:
|
191
|
+
"""
|
192
|
+
Mixin class for exporting validation metrics or prediction results in various formats.
|
193
|
+
|
194
|
+
This class provides utilities to export performance metrics (e.g., mAP, precision, recall) or prediction results
|
195
|
+
from classification, object detection, segmentation, or pose estimation tasks into various formats, Pandas DataFrame
|
196
|
+
CSV, XML, HTML, JSON and SQLite (SQL)
|
197
|
+
|
198
|
+
Methods:
|
199
|
+
to_df(): Convert summary to a Pandas DataFrame.
|
200
|
+
to_csv(): Export results as a CSV string.
|
201
|
+
to_xml(): Export results as an XML string (requires `lxml`).
|
202
|
+
to_html(): Export results as an HTML table.
|
203
|
+
to_json(): Export results as a JSON string.
|
204
|
+
tojson(): Deprecated alias for `to_json()`.
|
205
|
+
to_sql(): Export results to an SQLite database.
|
206
|
+
|
207
|
+
Examples:
|
208
|
+
>>> model = YOLO("yolov8n.pt")
|
209
|
+
>>> results = model("image.jpg")
|
210
|
+
>>> df = results.to_df()
|
211
|
+
>>> print(df)
|
212
|
+
>>> csv_data = results.to_csv()
|
213
|
+
>>> results.to_sql(table_name="yolo_results")
|
214
|
+
"""
|
215
|
+
|
216
|
+
def to_df(self, normalize=False, decimals=5):
|
217
|
+
"""
|
218
|
+
Create a pandas DataFrame from the prediction results summary or validation metrics.
|
219
|
+
|
220
|
+
Args:
|
221
|
+
normalize (bool, optional): Normalize numerical values for easier comparison. Defaults to False.
|
222
|
+
decimals (int, optional): Decimal places to round floats. Defaults to 5.
|
223
|
+
|
224
|
+
Returns:
|
225
|
+
(DataFrame): DataFrame containing the summary data.
|
226
|
+
"""
|
227
|
+
import pandas as pd # scope for faster 'import ultralytics'
|
228
|
+
|
229
|
+
return pd.DataFrame(self.summary(normalize=normalize, decimals=decimals))
|
230
|
+
|
231
|
+
def to_csv(self, normalize=False, decimals=5):
|
232
|
+
"""
|
233
|
+
Export results to CSV string format.
|
234
|
+
|
235
|
+
Args:
|
236
|
+
normalize (bool, optional): Normalize numeric values. Defaults to False.
|
237
|
+
decimals (int, optional): Decimal precision. Defaults to 5.
|
238
|
+
|
239
|
+
Returns:
|
240
|
+
(str): CSV content as string.
|
241
|
+
"""
|
242
|
+
return self.to_df(normalize=normalize, decimals=decimals).to_csv()
|
243
|
+
|
244
|
+
def to_xml(self, normalize=False, decimals=5):
|
245
|
+
"""
|
246
|
+
Export results to XML format.
|
247
|
+
|
248
|
+
Args:
|
249
|
+
normalize (bool, optional): Normalize numeric values. Defaults to False.
|
250
|
+
decimals (int, optional): Decimal precision. Defaults to 5.
|
251
|
+
|
252
|
+
Returns:
|
253
|
+
(str): XML string.
|
254
|
+
|
255
|
+
Note:
|
256
|
+
Requires `lxml` package to be installed.
|
257
|
+
"""
|
258
|
+
from ultralytics.utils.checks import check_requirements
|
259
|
+
|
260
|
+
check_requirements("lxml")
|
261
|
+
df = self.to_df(normalize=normalize, decimals=decimals)
|
262
|
+
return '<?xml version="1.0" encoding="utf-8"?>\n<root></root>' if df.empty else df.to_xml()
|
263
|
+
|
264
|
+
def to_html(self, normalize=False, decimals=5, index=False):
|
265
|
+
"""
|
266
|
+
Export results to HTML table format.
|
267
|
+
|
268
|
+
Args:
|
269
|
+
normalize (bool, optional): Normalize numeric values. Defaults to False.
|
270
|
+
decimals (int, optional): Decimal precision. Defaults to 5.
|
271
|
+
index (bool, optional): Whether to include index column in the HTML table. Defaults to False.
|
272
|
+
|
273
|
+
Returns:
|
274
|
+
(str): HTML representation of the results.
|
275
|
+
"""
|
276
|
+
df = self.to_df(normalize=normalize, decimals=decimals)
|
277
|
+
return "<table></table>" if df.empty else df.to_html(index=index)
|
278
|
+
|
279
|
+
def tojson(self, normalize=False, decimals=5):
|
280
|
+
"""Deprecated version of to_json()."""
|
281
|
+
LOGGER.warning("'result.tojson()' is deprecated, replace with 'result.to_json()'.")
|
282
|
+
return self.to_json(normalize, decimals)
|
283
|
+
|
284
|
+
def to_json(self, normalize=False, decimals=5):
|
285
|
+
"""
|
286
|
+
Export results to JSON format.
|
287
|
+
|
288
|
+
Args:
|
289
|
+
normalize (bool, optional): Normalize numeric values. Defaults to False.
|
290
|
+
decimals (int, optional): Decimal precision. Defaults to 5.
|
291
|
+
|
292
|
+
Returns:
|
293
|
+
(str): JSON-formatted string of the results.
|
294
|
+
"""
|
295
|
+
return self.to_df(normalize=normalize, decimals=decimals).to_json(orient="records", indent=2)
|
296
|
+
|
297
|
+
def to_sql(self, normalize=False, decimals=5, table_name="results", db_path="results.db"):
|
298
|
+
"""
|
299
|
+
Save results to an SQLite database.
|
300
|
+
|
301
|
+
Args:
|
302
|
+
normalize (bool, optional): Normalize numeric values. Defaults to False.
|
303
|
+
decimals (int, optional): Decimal precision. Defaults to 5.
|
304
|
+
table_name (str, optional): Name of the SQL table. Defaults to "results".
|
305
|
+
db_path (str, optional): SQLite database file path. Defaults to "results.db".
|
306
|
+
"""
|
307
|
+
df = self.to_df(normalize, decimals)
|
308
|
+
if df.empty or df.columns.empty: # Exit if df is None or has no columns (i.e., no schema)
|
309
|
+
return
|
310
|
+
|
311
|
+
import sqlite3
|
312
|
+
|
313
|
+
conn = sqlite3.connect(db_path)
|
314
|
+
cursor = conn.cursor()
|
315
|
+
|
316
|
+
# Dynamically create table schema based on summary to support prediction and validation results export
|
317
|
+
columns = []
|
318
|
+
for col in df.columns:
|
319
|
+
sample_val = df[col].dropna().iloc[0] if not df[col].dropna().empty else ""
|
320
|
+
if isinstance(sample_val, dict):
|
321
|
+
col_type = "TEXT"
|
322
|
+
elif isinstance(sample_val, (float, int)):
|
323
|
+
col_type = "REAL"
|
324
|
+
else:
|
325
|
+
col_type = "TEXT"
|
326
|
+
columns.append(f'"{col}" {col_type}') # Quote column names to handle special characters like hyphens
|
327
|
+
|
328
|
+
# Create table (Drop table from db if it's already exist)
|
329
|
+
cursor.execute(f'DROP TABLE IF EXISTS "{table_name}"')
|
330
|
+
cursor.execute(f'CREATE TABLE "{table_name}" (id INTEGER PRIMARY KEY AUTOINCREMENT, {", ".join(columns)})')
|
331
|
+
|
332
|
+
for _, row in df.iterrows():
|
333
|
+
values = [json.dumps(v) if isinstance(v, dict) else v for v in row]
|
334
|
+
column_names = ", ".join(f'"{col}"' for col in df.columns)
|
335
|
+
placeholders = ", ".join("?" for _ in df.columns)
|
336
|
+
cursor.execute(f'INSERT INTO "{table_name}" ({column_names}) VALUES ({placeholders})', values)
|
337
|
+
|
338
|
+
conn.commit()
|
339
|
+
conn.close()
|
340
|
+
LOGGER.info(f"Results saved to SQL table '{table_name}' in '{db_path}'.")
|
341
|
+
|
342
|
+
|
190
343
|
class SimpleClass:
|
191
344
|
"""
|
192
345
|
A simple base class for creating objects with string representations of their attributes.
|
ultralytics/utils/benchmarks.py
CHANGED
ultralytics/utils/checks.py
CHANGED
@@ -165,6 +165,15 @@ def check_imgsz(imgsz, stride=32, min_dim=1, max_dim=2, floor=0):
|
|
165
165
|
return sz
|
166
166
|
|
167
167
|
|
168
|
+
@functools.lru_cache
|
169
|
+
def check_uv():
|
170
|
+
"""Check if uv is installed and can run successfully."""
|
171
|
+
try:
|
172
|
+
return subprocess.run(["uv", "-V"], capture_output=True).returncode == 0
|
173
|
+
except FileNotFoundError:
|
174
|
+
return False
|
175
|
+
|
176
|
+
|
168
177
|
@functools.lru_cache
|
169
178
|
def check_version(
|
170
179
|
current: str = "0.0.0",
|
@@ -388,21 +397,27 @@ def check_requirements(requirements=ROOT.parent / "requirements.txt", exclude=()
|
|
388
397
|
pkgs.append(r)
|
389
398
|
|
390
399
|
@Retry(times=2, delay=1)
|
391
|
-
def attempt_install(packages, commands):
|
392
|
-
"""Attempt
|
393
|
-
|
400
|
+
def attempt_install(packages, commands, use_uv):
|
401
|
+
"""Attempt package installation with uv if available, falling back to pip."""
|
402
|
+
if use_uv:
|
403
|
+
# Note requires --break-system-packages on ARM64 dockerfile
|
404
|
+
cmd = f"uv pip install --system --no-cache-dir {packages} {commands} --index-strategy=unsafe-best-match --break-system-packages --prerelease=allow"
|
405
|
+
else:
|
406
|
+
cmd = f"pip install --no-cache-dir {packages} {commands}"
|
407
|
+
return subprocess.check_output(cmd, shell=True).decode()
|
394
408
|
|
395
409
|
s = " ".join(f'"{x}"' for x in pkgs) # console string
|
396
410
|
if s:
|
397
411
|
if install and AUTOINSTALL: # check environment variable
|
412
|
+
# Note uv fails on arm64 macOS and Raspberry Pi runners
|
398
413
|
n = len(pkgs) # number of packages updates
|
399
414
|
LOGGER.info(f"{prefix} Ultralytics requirement{'s' * (n > 1)} {pkgs} not found, attempting AutoUpdate...")
|
400
415
|
try:
|
401
416
|
t = time.time()
|
402
417
|
assert ONLINE, "AutoUpdate skipped (offline)"
|
403
|
-
LOGGER.info(attempt_install(s, cmds))
|
418
|
+
LOGGER.info(attempt_install(s, cmds, use_uv=not ARM64 and check_uv()))
|
404
419
|
dt = time.time() - t
|
405
|
-
LOGGER.info(f"{prefix} AutoUpdate success ✅ {dt:.1f}s
|
420
|
+
LOGGER.info(f"{prefix} AutoUpdate success ✅ {dt:.1f}s")
|
406
421
|
LOGGER.warning(
|
407
422
|
f"{prefix} {colorstr('bold', 'Restart runtime or rerun command for updates to take effect')}\n"
|
408
423
|
)
|
@@ -894,7 +909,6 @@ check_torchvision() # check torch-torchvision compatibility
|
|
894
909
|
|
895
910
|
# Define constants
|
896
911
|
IS_PYTHON_3_8 = PYTHON_VERSION.startswith("3.8")
|
897
|
-
IS_PYTHON_3_11 = PYTHON_VERSION.startswith("3.11")
|
898
912
|
IS_PYTHON_3_12 = PYTHON_VERSION.startswith("3.12")
|
899
913
|
IS_PYTHON_3_13 = PYTHON_VERSION.startswith("3.13")
|
900
914
|
|
ultralytics/utils/metrics.py
CHANGED
@@ -8,7 +8,7 @@ from pathlib import Path
|
|
8
8
|
import numpy as np
|
9
9
|
import torch
|
10
10
|
|
11
|
-
from ultralytics.utils import LOGGER, SimpleClass, TryExcept, checks, plt_settings
|
11
|
+
from ultralytics.utils import LOGGER, DataExportMixin, SimpleClass, TryExcept, checks, plt_settings
|
12
12
|
|
13
13
|
OKS_SIGMA = (
|
14
14
|
np.array([0.26, 0.25, 0.25, 0.35, 0.35, 0.79, 0.79, 0.72, 0.72, 0.62, 0.62, 1.07, 1.07, 0.87, 0.87, 0.89, 0.89])
|
@@ -865,7 +865,7 @@ class Metric(SimpleClass):
|
|
865
865
|
]
|
866
866
|
|
867
867
|
|
868
|
-
class DetMetrics(SimpleClass):
|
868
|
+
class DetMetrics(SimpleClass, DataExportMixin):
|
869
869
|
"""
|
870
870
|
Utility class for computing detection metrics such as precision, recall, and mean average precision (mAP).
|
871
871
|
|
@@ -961,8 +961,29 @@ class DetMetrics(SimpleClass):
|
|
961
961
|
"""Return dictionary of computed performance metrics and statistics."""
|
962
962
|
return self.box.curves_results
|
963
963
|
|
964
|
+
def summary(self, **kwargs):
|
965
|
+
"""Returns per-class detection metrics with shared scalar values included."""
|
966
|
+
scalars = {
|
967
|
+
"box-map": self.box.map,
|
968
|
+
"box-map50": self.box.map50,
|
969
|
+
"box-map75": self.box.map75,
|
970
|
+
}
|
971
|
+
per_class = {
|
972
|
+
"box-p": self.box.p,
|
973
|
+
"box-r": self.box.r,
|
974
|
+
"box-f1": self.box.f1,
|
975
|
+
}
|
976
|
+
return [
|
977
|
+
{
|
978
|
+
"class_name": self.names[i] if hasattr(self, "names") and i in self.names else str(i),
|
979
|
+
**{k: v[i] for k, v in per_class.items()},
|
980
|
+
**scalars,
|
981
|
+
}
|
982
|
+
for i in range(len(next(iter(per_class.values()), [])))
|
983
|
+
]
|
964
984
|
|
965
|
-
|
985
|
+
|
986
|
+
class SegmentMetrics(SimpleClass, DataExportMixin):
|
966
987
|
"""
|
967
988
|
Calculates and aggregates detection and segmentation metrics over a given set of classes.
|
968
989
|
|
@@ -1097,6 +1118,29 @@ class SegmentMetrics(SimpleClass):
|
|
1097
1118
|
"""Return dictionary of computed performance metrics and statistics."""
|
1098
1119
|
return self.box.curves_results + self.seg.curves_results
|
1099
1120
|
|
1121
|
+
def summary(self, **kwargs):
|
1122
|
+
"""Returns per-class segmentation metrics with shared scalar values included (box + mask)."""
|
1123
|
+
scalars = {
|
1124
|
+
"box-map": self.box.map,
|
1125
|
+
"box-map50": self.box.map50,
|
1126
|
+
"box-map75": self.box.map75,
|
1127
|
+
"mask-map": self.seg.map,
|
1128
|
+
"mask-map50": self.seg.map50,
|
1129
|
+
"mask-map75": self.seg.map75,
|
1130
|
+
}
|
1131
|
+
per_class = {
|
1132
|
+
"box-p": self.box.p,
|
1133
|
+
"box-r": self.box.r,
|
1134
|
+
"box-f1": self.box.f1,
|
1135
|
+
"mask-p": self.seg.p,
|
1136
|
+
"mask-r": self.seg.r,
|
1137
|
+
"mask-f1": self.seg.f1,
|
1138
|
+
}
|
1139
|
+
return [
|
1140
|
+
{"class_name": self.names[i], **{k: v[i] for k, v in per_class.items()}, **scalars}
|
1141
|
+
for i in range(len(next(iter(per_class.values()), [])))
|
1142
|
+
]
|
1143
|
+
|
1100
1144
|
|
1101
1145
|
class PoseMetrics(SegmentMetrics):
|
1102
1146
|
"""
|
@@ -1229,8 +1273,31 @@ class PoseMetrics(SegmentMetrics):
|
|
1229
1273
|
"""Return dictionary of computed performance metrics and statistics."""
|
1230
1274
|
return self.box.curves_results + self.pose.curves_results
|
1231
1275
|
|
1276
|
+
def summary(self, **kwargs):
|
1277
|
+
"""Returns per-class pose metrics with shared scalar values included (box + pose)."""
|
1278
|
+
scalars = {
|
1279
|
+
"box-map": self.box.map,
|
1280
|
+
"box-map50": self.box.map50,
|
1281
|
+
"box-map75": self.box.map75,
|
1282
|
+
"pose-map": self.pose.map,
|
1283
|
+
"pose-map50": self.pose.map50,
|
1284
|
+
"pose-map75": self.pose.map75,
|
1285
|
+
}
|
1286
|
+
per_class = {
|
1287
|
+
"box-p": self.box.p,
|
1288
|
+
"box-r": self.box.r,
|
1289
|
+
"box-f1": self.box.f1,
|
1290
|
+
"pose-p": self.pose.p,
|
1291
|
+
"pose-r": self.pose.r,
|
1292
|
+
"pose-f1": self.pose.f1,
|
1293
|
+
}
|
1294
|
+
return [
|
1295
|
+
{"class_name": self.names[i], **{k: v[i] for k, v in per_class.items()}, **scalars}
|
1296
|
+
for i in range(len(next(iter(per_class.values()), [])))
|
1297
|
+
]
|
1298
|
+
|
1232
1299
|
|
1233
|
-
class ClassifyMetrics(SimpleClass):
|
1300
|
+
class ClassifyMetrics(SimpleClass, DataExportMixin):
|
1234
1301
|
"""
|
1235
1302
|
Class for computing classification metrics including top-1 and top-5 accuracy.
|
1236
1303
|
|
@@ -1286,8 +1353,12 @@ class ClassifyMetrics(SimpleClass):
|
|
1286
1353
|
"""Return a list of curves for accessing specific metrics curves."""
|
1287
1354
|
return []
|
1288
1355
|
|
1356
|
+
def summary(self, **kwargs):
|
1357
|
+
"""Returns a single-row summary for classification metrics (top1/top5)."""
|
1358
|
+
return [{"classify-top1": self.top1, "classify-top5": self.top5}]
|
1359
|
+
|
1289
1360
|
|
1290
|
-
class OBBMetrics(SimpleClass):
|
1361
|
+
class OBBMetrics(SimpleClass, DataExportMixin):
|
1291
1362
|
"""
|
1292
1363
|
Metrics for evaluating oriented bounding box (OBB) detection.
|
1293
1364
|
|
@@ -1316,6 +1387,7 @@ class OBBMetrics(SimpleClass):
|
|
1316
1387
|
self.names = names
|
1317
1388
|
self.box = Metric()
|
1318
1389
|
self.speed = {"preprocess": 0.0, "inference": 0.0, "loss": 0.0, "postprocess": 0.0}
|
1390
|
+
self.task = "obb"
|
1319
1391
|
|
1320
1392
|
def process(self, tp, conf, pred_cls, target_cls, on_plot=None):
|
1321
1393
|
"""
|
@@ -1383,3 +1455,16 @@ class OBBMetrics(SimpleClass):
|
|
1383
1455
|
def curves_results(self):
|
1384
1456
|
"""Return a list of curves for accessing specific metrics curves."""
|
1385
1457
|
return []
|
1458
|
+
|
1459
|
+
def summary(self, **kwargs):
|
1460
|
+
"""Returns per-class detection metrics with shared scalar values included."""
|
1461
|
+
scalars = {
|
1462
|
+
"box-map": self.box.map,
|
1463
|
+
"box-map50": self.box.map50,
|
1464
|
+
"box-map75": self.box.map75,
|
1465
|
+
}
|
1466
|
+
per_class = {"box-p": self.box.p, "box-r": self.box.r, "box-f1": self.box.f1}
|
1467
|
+
return [
|
1468
|
+
{"class_name": self.names[i], **{k: v[i] for k, v in per_class.items()}, **scalars}
|
1469
|
+
for i in range(len(next(iter(per_class.values()), [])))
|
1470
|
+
]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ultralytics
|
3
|
-
Version: 8.3.
|
3
|
+
Version: 8.3.140
|
4
4
|
Summary: Ultralytics YOLO 🚀 for SOTA object detection, multi-object tracking, instance segmentation, pose estimation and image classification.
|
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,13 +1,13 @@
|
|
1
1
|
tests/__init__.py,sha256=xnMhv3O_DF1YrW4zk__ZywQzAaoTDjPKPoiI1Ktss1w,670
|
2
2
|
tests/conftest.py,sha256=rsIAipRKfrVNoTaJ1LdpYue8AbcJ_fr3d3WIlM_6uXY,2982
|
3
3
|
tests/test_cli.py,sha256=vXUC_EK0fa87JRhHsCOZf7AJQ5_Jm1sL8u-yhmsaQh0,5851
|
4
|
-
tests/test_cuda.py,sha256=
|
4
|
+
tests/test_cuda.py,sha256=k4i-6lrp_hczJjbLk_uJOTfMeZZN5o3Dj9jbPA0TzB4,7912
|
5
5
|
tests/test_engine.py,sha256=aGqZ8P7QO5C_nOa1b4FOyk92Ysdk5WiP-ST310Vyxys,4962
|
6
6
|
tests/test_exports.py,sha256=dhZn86LdbapW15RthQF870LGxDjC1MUZhlGdBgPmgIQ,9716
|
7
7
|
tests/test_integrations.py,sha256=dQteeRsRVuT_p5-T88-7jqT65Zm9iAXkyKg-KQ1_TQ8,6341
|
8
|
-
tests/test_python.py,sha256=
|
9
|
-
tests/test_solutions.py,sha256=
|
10
|
-
ultralytics/__init__.py,sha256=
|
8
|
+
tests/test_python.py,sha256=Zx9OlPN11_D1WSLpi9nPFqORNHNz0lEn6mxVNL2ZHjE,25852
|
9
|
+
tests/test_solutions.py,sha256=7n4CqKj2guj09UFKe4jufrrC16xRBUIjiRAfGDoAMI8,12808
|
10
|
+
ultralytics/__init__.py,sha256=27HzhLPFDZjawOY0VuVN8Sn9RoiF9R4NJj3_CBuiuIs,730
|
11
11
|
ultralytics/assets/bus.jpg,sha256=wCAZxJecGR63Od3ZRERe9Aja1Weayrb9Ug751DS_vGM,137419
|
12
12
|
ultralytics/assets/zidane.jpg,sha256=Ftc4aeMmen1O0A3o6GCDO9FlfBslLpTAw0gnetx7bts,50427
|
13
13
|
ultralytics/cfg/__init__.py,sha256=mpvLR68Iff4J59zYGhysSl8VwIVVzV_VMOYeVdqnYj4,39544
|
@@ -118,10 +118,10 @@ ultralytics/data/scripts/get_coco.sh,sha256=UuJpJeo3qQpTHVINeOpmP0NYmg8PhEFE3A8J
|
|
118
118
|
ultralytics/data/scripts/get_coco128.sh,sha256=qmRQl_hOKrsdHrTrnyQuFIH01oDz3lfaz138OgGfLt8,650
|
119
119
|
ultralytics/data/scripts/get_imagenet.sh,sha256=hr42H16bM47iT27rgS7MpEo-GeOZAYUQXgr0B2cwn48,1705
|
120
120
|
ultralytics/engine/__init__.py,sha256=lm6MckFYCPTbqIoX7w0s_daxdjNeBeKW6DXppv1-QUM,70
|
121
|
-
ultralytics/engine/exporter.py,sha256=
|
121
|
+
ultralytics/engine/exporter.py,sha256=BZWa7Mnl1BPvbPiD-RJs6M5Bca4sm3_MQgjoHesvXEs,70949
|
122
122
|
ultralytics/engine/model.py,sha256=BtC5KYNrdfhryrS7b6ZXDIsmtObEeIDTePCv1gO4br4,52952
|
123
123
|
ultralytics/engine/predictor.py,sha256=rZ5mIPeejkxUerpTfUf_1rSAklOR3THqoejlil4C04w,21651
|
124
|
-
ultralytics/engine/results.py,sha256=
|
124
|
+
ultralytics/engine/results.py,sha256=2sNNhAc2zaIRaQBXl_36gAKK31V8tgNDcgC4ZPiGqKI,70072
|
125
125
|
ultralytics/engine/trainer.py,sha256=xdgNAgq6umJ6915tiCK3U22NeY7w1HnvmAhXlwS_hYI,38955
|
126
126
|
ultralytics/engine/tuner.py,sha256=zEW1UpLlZ6N4xbvS7MxICkshRlaFgLNfuADA0VfRpao,12629
|
127
127
|
ultralytics/engine/validator.py,sha256=f9UUv3QqQStLrO1nojrHkdS58qYQxKXaoIQQria6WyA,17054
|
@@ -233,11 +233,11 @@ ultralytics/trackers/utils/__init__.py,sha256=lm6MckFYCPTbqIoX7w0s_daxdjNeBeKW6D
|
|
233
233
|
ultralytics/trackers/utils/gmc.py,sha256=843LlmqWuXdUULBNpxVCZlil-_2QG-UwvscUCFbpGjA,14541
|
234
234
|
ultralytics/trackers/utils/kalman_filter.py,sha256=A0CqOnnaKH6kr0XwuHzyHmIU6aJAjJYxF9jVlNBKZHo,21326
|
235
235
|
ultralytics/trackers/utils/matching.py,sha256=7eIufSdeN7cXuFMjvcfvz0Ldq84m4YKZl5IGxBR8IIo,7169
|
236
|
-
ultralytics/utils/__init__.py,sha256=
|
236
|
+
ultralytics/utils/__init__.py,sha256=7VT2VSCIgDPInuNKO0sy2_3-qUwuCafLG0wF4wAyjBg,59059
|
237
237
|
ultralytics/utils/autobatch.py,sha256=kg05q2qKg74y_Uq2vvr01i3KhLfpVR7sT0IXBt3_kyI,4921
|
238
238
|
ultralytics/utils/autodevice.py,sha256=OKZfTbswg6SlsYGCGMqROkA-451CXGG47oeyC5Q1kFM,7232
|
239
|
-
ultralytics/utils/benchmarks.py,sha256=
|
240
|
-
ultralytics/utils/checks.py,sha256=
|
239
|
+
ultralytics/utils/benchmarks.py,sha256=iqjxD29srcCpimtAhbSidpsjnUlMhNR5S6QGPZyz16I,30287
|
240
|
+
ultralytics/utils/checks.py,sha256=SinI5gY-znVbQ-JXk1JaHIlSp2kuBv92Rv99NWFzOFg,33763
|
241
241
|
ultralytics/utils/dist.py,sha256=aytW0JEkcA5ZTZucV92ot7Bn-apiej8aLk3QNWicjAc,4103
|
242
242
|
ultralytics/utils/downloads.py,sha256=G1nd7c7Gwjf58nZzDVpXDtoFtzhZYbjKBnwbZVMWRG0,22333
|
243
243
|
ultralytics/utils/errors.py,sha256=vY9h2evFSrHnZdHJVVrmm8Zzw4qVDLyo9DeYW5g0dFk,1573
|
@@ -245,7 +245,7 @@ ultralytics/utils/export.py,sha256=Rr5R3GdJBapJJt1XHkH6VQwYN52-L_7wGiRDCgnb7BY,8
|
|
245
245
|
ultralytics/utils/files.py,sha256=0K4O1cgqRiXaDw7EQK13TqA5SME_RrvfDVQSPetNr5w,8042
|
246
246
|
ultralytics/utils/instance.py,sha256=UOEsXR9V-bXNRk6BTonASBEgeMqvzzAk4S7VdXZJUAM,18090
|
247
247
|
ultralytics/utils/loss.py,sha256=Woc_rj7ptCyezHdylEygXMeSEgivYu_B9jJHD4UwxWE,37607
|
248
|
-
ultralytics/utils/metrics.py,sha256=
|
248
|
+
ultralytics/utils/metrics.py,sha256=8x4S7y-rBKRkM47f_o7jfMHA1Bz8SDq3t-R1FXlQNEM,59267
|
249
249
|
ultralytics/utils/ops.py,sha256=YFwPrKlPcgEmgAWqnJVR0Ccx5NQgp5e3P-YYHwVSP0k,34779
|
250
250
|
ultralytics/utils/patches.py,sha256=_dhIU_eDklQE-aWIjpyjPHl_wOwZoGuIUQnXgdSwk_A,5020
|
251
251
|
ultralytics/utils/plotting.py,sha256=oFq19c3tRng-dKHEH-j-S_wLG4CZ_mk8wqE_Gab2H8A,47221
|
@@ -264,9 +264,9 @@ ultralytics/utils/callbacks/neptune.py,sha256=yYUgEgSv6L39sSev6vjwhAWU3DlPDsbSDV
|
|
264
264
|
ultralytics/utils/callbacks/raytune.py,sha256=A8amUGpux7dYES-L1iSeMoMXBySGWCD1aUqT7vcG-pU,1284
|
265
265
|
ultralytics/utils/callbacks/tensorboard.py,sha256=jgYnym3cUQFAgN1GzTyO7l3jINtfAh8zhrllDvnLuVQ,5339
|
266
266
|
ultralytics/utils/callbacks/wb.py,sha256=iDRFXI4IIDm8R5OI89DMTmjs8aHLo1HRCLkOFKdaMG4,7507
|
267
|
-
ultralytics-8.3.
|
268
|
-
ultralytics-8.3.
|
269
|
-
ultralytics-8.3.
|
270
|
-
ultralytics-8.3.
|
271
|
-
ultralytics-8.3.
|
272
|
-
ultralytics-8.3.
|
267
|
+
ultralytics-8.3.140.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
268
|
+
ultralytics-8.3.140.dist-info/METADATA,sha256=ubcLXOXQF7RbhxNBCUSmLJxf6IhihoPeoaBx5LU1r0M,37200
|
269
|
+
ultralytics-8.3.140.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
|
270
|
+
ultralytics-8.3.140.dist-info/entry_points.txt,sha256=YM_wiKyTe9yRrsEfqvYolNO5ngwfoL4-NwgKzc8_7sI,93
|
271
|
+
ultralytics-8.3.140.dist-info/top_level.txt,sha256=XP49TwiMw4QGsvTLSYiJhz1xF_k7ev5mQ8jJXaXi45Q,12
|
272
|
+
ultralytics-8.3.140.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|