ultralytics 8.3.10__py3-none-any.whl → 8.3.12__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.

Potentially problematic release.


This version of ultralytics might be problematic. Click here for more details.

Files changed (33) hide show
  1. tests/test_cli.py +4 -1
  2. tests/test_cuda.py +13 -1
  3. ultralytics/__init__.py +1 -3
  4. ultralytics/cfg/__init__.py +2 -35
  5. ultralytics/cfg/solutions/default.yaml +1 -0
  6. ultralytics/data/annotator.py +1 -1
  7. ultralytics/engine/exporter.py +56 -51
  8. ultralytics/engine/model.py +33 -33
  9. ultralytics/engine/results.py +1 -1
  10. ultralytics/engine/tuner.py +3 -3
  11. ultralytics/models/sam/predict.py +12 -5
  12. ultralytics/models/yolo/detect/predict.py +1 -1
  13. ultralytics/models/yolo/detect/train.py +1 -1
  14. ultralytics/models/yolo/detect/val.py +1 -1
  15. ultralytics/models/yolo/model.py +1 -1
  16. ultralytics/nn/autobackend.py +1 -1
  17. ultralytics/solutions/analytics.py +151 -264
  18. ultralytics/utils/benchmarks.py +2 -2
  19. ultralytics/utils/checks.py +1 -1
  20. ultralytics/utils/downloads.py +1 -1
  21. ultralytics/utils/files.py +2 -2
  22. ultralytics/utils/tuner.py +1 -1
  23. {ultralytics-8.3.10.dist-info → ultralytics-8.3.12.dist-info}/METADATA +4 -5
  24. {ultralytics-8.3.10.dist-info → ultralytics-8.3.12.dist-info}/RECORD +28 -33
  25. ultralytics/data/explorer/__init__.py +0 -5
  26. ultralytics/data/explorer/explorer.py +0 -460
  27. ultralytics/data/explorer/gui/__init__.py +0 -1
  28. ultralytics/data/explorer/gui/dash.py +0 -269
  29. ultralytics/data/explorer/utils.py +0 -167
  30. {ultralytics-8.3.10.dist-info → ultralytics-8.3.12.dist-info}/LICENSE +0 -0
  31. {ultralytics-8.3.10.dist-info → ultralytics-8.3.12.dist-info}/WHEEL +0 -0
  32. {ultralytics-8.3.10.dist-info → ultralytics-8.3.12.dist-info}/entry_points.txt +0 -0
  33. {ultralytics-8.3.10.dist-info → ultralytics-8.3.12.dist-info}/top_level.txt +0 -0
@@ -1,269 +0,0 @@
1
- # Ultralytics YOLO 🚀, AGPL-3.0 license
2
-
3
- import sys
4
- import time
5
- from threading import Thread
6
-
7
- from ultralytics import Explorer
8
- from ultralytics.utils import ROOT, SETTINGS
9
- from ultralytics.utils.checks import check_requirements
10
-
11
- check_requirements(("streamlit>=1.29.0", "streamlit-select>=0.3"))
12
-
13
- import streamlit as st
14
- from streamlit_select import image_select
15
-
16
-
17
- def _get_explorer():
18
- """Initializes and returns an instance of the Explorer class."""
19
- exp = Explorer(data=st.session_state.get("dataset"), model=st.session_state.get("model"))
20
- thread = Thread(
21
- target=exp.create_embeddings_table,
22
- kwargs={"force": st.session_state.get("force_recreate_embeddings"), "split": st.session_state.get("split")},
23
- )
24
- thread.start()
25
- progress_bar = st.progress(0, text="Creating embeddings table...")
26
- while exp.progress < 1:
27
- time.sleep(0.1)
28
- progress_bar.progress(exp.progress, text=f"Progress: {exp.progress * 100}%")
29
- thread.join()
30
- st.session_state["explorer"] = exp
31
- progress_bar.empty()
32
-
33
-
34
- def init_explorer_form(data=None, model=None):
35
- """Initializes an Explorer instance and creates embeddings table with progress tracking."""
36
- if data is None:
37
- datasets = ROOT / "cfg" / "datasets"
38
- ds = [d.name for d in datasets.glob("*.yaml")]
39
- else:
40
- ds = [data]
41
-
42
- prefixes = ["yolov8", "yolo11"]
43
- sizes = ["n", "s", "m", "l", "x"]
44
- tasks = ["", "-seg", "-pose"]
45
- if model is None:
46
- models = [f"{p}{s}{t}" for p in prefixes for s in sizes for t in tasks]
47
- else:
48
- models = [model]
49
-
50
- splits = ["train", "val", "test"]
51
-
52
- with st.form(key="explorer_init_form"):
53
- col1, col2, col3 = st.columns(3)
54
- with col1:
55
- st.selectbox("Select dataset", ds, key="dataset")
56
- with col2:
57
- st.selectbox("Select model", models, key="model")
58
- with col3:
59
- st.selectbox("Select split", splits, key="split")
60
- st.checkbox("Force recreate embeddings", key="force_recreate_embeddings")
61
-
62
- st.form_submit_button("Explore", on_click=_get_explorer)
63
-
64
-
65
- def query_form():
66
- """Sets up a form in Streamlit to initialize Explorer with dataset and model selection."""
67
- with st.form("query_form"):
68
- col1, col2 = st.columns([0.8, 0.2])
69
- with col1:
70
- st.text_input(
71
- "Query",
72
- "WHERE labels LIKE '%person%' AND labels LIKE '%dog%'",
73
- label_visibility="collapsed",
74
- key="query",
75
- )
76
- with col2:
77
- st.form_submit_button("Query", on_click=run_sql_query)
78
-
79
-
80
- def ai_query_form():
81
- """Sets up a Streamlit form for user input to initialize Explorer with dataset and model selection."""
82
- with st.form("ai_query_form"):
83
- col1, col2 = st.columns([0.8, 0.2])
84
- with col1:
85
- st.text_input("Query", "Show images with 1 person and 1 dog", label_visibility="collapsed", key="ai_query")
86
- with col2:
87
- st.form_submit_button("Ask AI", on_click=run_ai_query)
88
-
89
-
90
- def find_similar_imgs(imgs):
91
- """Initializes a Streamlit form for AI-based image querying with custom input."""
92
- exp = st.session_state["explorer"]
93
- similar = exp.get_similar(img=imgs, limit=st.session_state.get("limit"), return_type="arrow")
94
- paths = similar.to_pydict()["im_file"]
95
- st.session_state["imgs"] = paths
96
- st.session_state["res"] = similar
97
-
98
-
99
- def similarity_form(selected_imgs):
100
- """Initializes a form for AI-based image querying with custom input in Streamlit."""
101
- st.write("Similarity Search")
102
- with st.form("similarity_form"):
103
- subcol1, subcol2 = st.columns([1, 1])
104
- with subcol1:
105
- st.number_input(
106
- "limit", min_value=None, max_value=None, value=25, label_visibility="collapsed", key="limit"
107
- )
108
-
109
- with subcol2:
110
- disabled = not len(selected_imgs)
111
- st.write("Selected: ", len(selected_imgs))
112
- st.form_submit_button(
113
- "Search",
114
- disabled=disabled,
115
- on_click=find_similar_imgs,
116
- args=(selected_imgs,),
117
- )
118
- if disabled:
119
- st.error("Select at least one image to search.")
120
-
121
-
122
- # def persist_reset_form():
123
- # with st.form("persist_reset"):
124
- # col1, col2 = st.columns([1, 1])
125
- # with col1:
126
- # st.form_submit_button("Reset", on_click=reset)
127
- #
128
- # with col2:
129
- # st.form_submit_button("Persist", on_click=update_state, args=("PERSISTING", True))
130
-
131
-
132
- def run_sql_query():
133
- """Executes an SQL query and returns the results."""
134
- st.session_state["error"] = None
135
- query = st.session_state.get("query")
136
- if query.rstrip().lstrip():
137
- exp = st.session_state["explorer"]
138
- res = exp.sql_query(query, return_type="arrow")
139
- st.session_state["imgs"] = res.to_pydict()["im_file"]
140
- st.session_state["res"] = res
141
-
142
-
143
- def run_ai_query():
144
- """Execute SQL query and update session state with query results."""
145
- if not SETTINGS["openai_api_key"]:
146
- st.session_state["error"] = (
147
- 'OpenAI API key not found in settings. Please run yolo settings openai_api_key="..."'
148
- )
149
- return
150
- import pandas # scope for faster 'import ultralytics'
151
-
152
- st.session_state["error"] = None
153
- query = st.session_state.get("ai_query")
154
- if query.rstrip().lstrip():
155
- exp = st.session_state["explorer"]
156
- res = exp.ask_ai(query)
157
- if not isinstance(res, pandas.DataFrame) or res.empty:
158
- st.session_state["error"] = "No results found using AI generated query. Try another query or rerun it."
159
- return
160
- st.session_state["imgs"] = res["im_file"].to_list()
161
- st.session_state["res"] = res
162
-
163
-
164
- def reset_explorer():
165
- """Resets the explorer to its initial state by clearing session variables."""
166
- st.session_state["explorer"] = None
167
- st.session_state["imgs"] = None
168
- st.session_state["error"] = None
169
-
170
-
171
- def utralytics_explorer_docs_callback():
172
- """Resets the explorer to its initial state by clearing session variables."""
173
- with st.container(border=True):
174
- st.image(
175
- "https://raw.githubusercontent.com/ultralytics/assets/main/logo/Ultralytics_Logotype_Original.svg",
176
- width=100,
177
- )
178
- st.markdown(
179
- "<p>This demo is built using Ultralytics Explorer API. Visit <a href='https://docs.ultralytics.com/datasets/explorer/'>API docs</a> to try examples & learn more</p>",
180
- unsafe_allow_html=True,
181
- help=None,
182
- )
183
- st.link_button("Ultrlaytics Explorer API", "https://docs.ultralytics.com/datasets/explorer/")
184
-
185
-
186
- def layout(data=None, model=None):
187
- """Resets explorer session variables and provides documentation with a link to API docs."""
188
- st.set_page_config(layout="wide", initial_sidebar_state="collapsed")
189
- st.markdown("<h1 style='text-align: center;'>Ultralytics Explorer Demo</h1>", unsafe_allow_html=True)
190
-
191
- if st.session_state.get("explorer") is None:
192
- init_explorer_form(data, model)
193
- return
194
-
195
- st.button(":arrow_backward: Select Dataset", on_click=reset_explorer)
196
- exp = st.session_state.get("explorer")
197
- col1, col2 = st.columns([0.75, 0.25], gap="small")
198
- imgs = []
199
- if st.session_state.get("error"):
200
- st.error(st.session_state["error"])
201
- elif st.session_state.get("imgs"):
202
- imgs = st.session_state.get("imgs")
203
- else:
204
- imgs = exp.table.to_lance().to_table(columns=["im_file"]).to_pydict()["im_file"]
205
- st.session_state["res"] = exp.table.to_arrow()
206
- total_imgs, selected_imgs = len(imgs), []
207
- with col1:
208
- subcol1, subcol2, subcol3, subcol4, subcol5 = st.columns(5)
209
- with subcol1:
210
- st.write("Max Images Displayed:")
211
- with subcol2:
212
- num = st.number_input(
213
- "Max Images Displayed",
214
- min_value=0,
215
- max_value=total_imgs,
216
- value=min(500, total_imgs),
217
- key="num_imgs_displayed",
218
- label_visibility="collapsed",
219
- )
220
- with subcol3:
221
- st.write("Start Index:")
222
- with subcol4:
223
- start_idx = st.number_input(
224
- "Start Index",
225
- min_value=0,
226
- max_value=total_imgs,
227
- value=0,
228
- key="start_index",
229
- label_visibility="collapsed",
230
- )
231
- with subcol5:
232
- reset = st.button("Reset", use_container_width=False, key="reset")
233
- if reset:
234
- st.session_state["imgs"] = None
235
- st.experimental_rerun()
236
-
237
- query_form()
238
- ai_query_form()
239
- if total_imgs:
240
- labels, boxes, masks, kpts, classes = None, None, None, None, None
241
- task = exp.model.task
242
- if st.session_state.get("display_labels"):
243
- labels = st.session_state.get("res").to_pydict()["labels"][start_idx : start_idx + num]
244
- boxes = st.session_state.get("res").to_pydict()["bboxes"][start_idx : start_idx + num]
245
- masks = st.session_state.get("res").to_pydict()["masks"][start_idx : start_idx + num]
246
- kpts = st.session_state.get("res").to_pydict()["keypoints"][start_idx : start_idx + num]
247
- classes = st.session_state.get("res").to_pydict()["cls"][start_idx : start_idx + num]
248
- imgs_displayed = imgs[start_idx : start_idx + num]
249
- selected_imgs = image_select(
250
- f"Total samples: {total_imgs}",
251
- images=imgs_displayed,
252
- use_container_width=False,
253
- # indices=[i for i in range(num)] if select_all else None,
254
- labels=labels,
255
- classes=classes,
256
- bboxes=boxes,
257
- masks=masks if task == "segment" else None,
258
- kpts=kpts if task == "pose" else None,
259
- )
260
-
261
- with col2:
262
- similarity_form(selected_imgs)
263
- st.checkbox("Labels", value=False, key="display_labels")
264
- utralytics_explorer_docs_callback()
265
-
266
-
267
- if __name__ == "__main__":
268
- kwargs = dict(zip(sys.argv[1::2], sys.argv[2::2]))
269
- layout(**kwargs)
@@ -1,167 +0,0 @@
1
- # Ultralytics YOLO 🚀, AGPL-3.0 license
2
-
3
- import getpass
4
- from typing import List
5
-
6
- import cv2
7
- import numpy as np
8
-
9
- from ultralytics.data.augment import LetterBox
10
- from ultralytics.utils import LOGGER as logger
11
- from ultralytics.utils import SETTINGS
12
- from ultralytics.utils.checks import check_requirements
13
- from ultralytics.utils.ops import xyxy2xywh
14
- from ultralytics.utils.plotting import plot_images
15
-
16
-
17
- def get_table_schema(vector_size):
18
- """Extracts and returns the schema of a database table."""
19
- from lancedb.pydantic import LanceModel, Vector
20
-
21
- class Schema(LanceModel):
22
- im_file: str
23
- labels: List[str]
24
- cls: List[int]
25
- bboxes: List[List[float]]
26
- masks: List[List[List[int]]]
27
- keypoints: List[List[List[float]]]
28
- vector: Vector(vector_size)
29
-
30
- return Schema
31
-
32
-
33
- def get_sim_index_schema():
34
- """Returns a LanceModel schema for a database table with specified vector size."""
35
- from lancedb.pydantic import LanceModel
36
-
37
- class Schema(LanceModel):
38
- idx: int
39
- im_file: str
40
- count: int
41
- sim_im_files: List[str]
42
-
43
- return Schema
44
-
45
-
46
- def sanitize_batch(batch, dataset_info):
47
- """Sanitizes input batch for inference, ensuring correct format and dimensions."""
48
- batch["cls"] = batch["cls"].flatten().int().tolist()
49
- box_cls_pair = sorted(zip(batch["bboxes"].tolist(), batch["cls"]), key=lambda x: x[1])
50
- batch["bboxes"] = [box for box, _ in box_cls_pair]
51
- batch["cls"] = [cls for _, cls in box_cls_pair]
52
- batch["labels"] = [dataset_info["names"][i] for i in batch["cls"]]
53
- batch["masks"] = batch["masks"].tolist() if "masks" in batch else [[[]]]
54
- batch["keypoints"] = batch["keypoints"].tolist() if "keypoints" in batch else [[[]]]
55
- return batch
56
-
57
-
58
- def plot_query_result(similar_set, plot_labels=True):
59
- """
60
- Plot images from the similar set.
61
-
62
- Args:
63
- similar_set (list): Pyarrow or pandas object containing the similar data points
64
- plot_labels (bool): Whether to plot labels or not
65
- """
66
- import pandas # scope for faster 'import ultralytics'
67
-
68
- similar_set = (
69
- similar_set.to_dict(orient="list") if isinstance(similar_set, pandas.DataFrame) else similar_set.to_pydict()
70
- )
71
- empty_masks = [[[]]]
72
- empty_boxes = [[]]
73
- images = similar_set.get("im_file", [])
74
- bboxes = similar_set.get("bboxes", []) if similar_set.get("bboxes") is not empty_boxes else []
75
- masks = similar_set.get("masks") if similar_set.get("masks")[0] != empty_masks else []
76
- kpts = similar_set.get("keypoints") if similar_set.get("keypoints")[0] != empty_masks else []
77
- cls = similar_set.get("cls", [])
78
-
79
- plot_size = 640
80
- imgs, batch_idx, plot_boxes, plot_masks, plot_kpts = [], [], [], [], []
81
- for i, imf in enumerate(images):
82
- im = cv2.imread(imf)
83
- im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
84
- h, w = im.shape[:2]
85
- r = min(plot_size / h, plot_size / w)
86
- imgs.append(LetterBox(plot_size, center=False)(image=im).transpose(2, 0, 1))
87
- if plot_labels:
88
- if len(bboxes) > i and len(bboxes[i]) > 0:
89
- box = np.array(bboxes[i], dtype=np.float32)
90
- box[:, [0, 2]] *= r
91
- box[:, [1, 3]] *= r
92
- plot_boxes.append(box)
93
- if len(masks) > i and len(masks[i]) > 0:
94
- mask = np.array(masks[i], dtype=np.uint8)[0]
95
- plot_masks.append(LetterBox(plot_size, center=False)(image=mask))
96
- if len(kpts) > i and kpts[i] is not None:
97
- kpt = np.array(kpts[i], dtype=np.float32)
98
- kpt[:, :, :2] *= r
99
- plot_kpts.append(kpt)
100
- batch_idx.append(np.ones(len(np.array(bboxes[i], dtype=np.float32))) * i)
101
- imgs = np.stack(imgs, axis=0)
102
- masks = np.stack(plot_masks, axis=0) if plot_masks else np.zeros(0, dtype=np.uint8)
103
- kpts = np.concatenate(plot_kpts, axis=0) if plot_kpts else np.zeros((0, 51), dtype=np.float32)
104
- boxes = xyxy2xywh(np.concatenate(plot_boxes, axis=0)) if plot_boxes else np.zeros(0, dtype=np.float32)
105
- batch_idx = np.concatenate(batch_idx, axis=0)
106
- cls = np.concatenate([np.array(c, dtype=np.int32) for c in cls], axis=0)
107
-
108
- return plot_images(
109
- imgs, batch_idx, cls, bboxes=boxes, masks=masks, kpts=kpts, max_subplots=len(images), save=False, threaded=False
110
- )
111
-
112
-
113
- def prompt_sql_query(query):
114
- """Plots images with optional labels from a similar data set."""
115
- check_requirements("openai>=1.6.1")
116
- from openai import OpenAI
117
-
118
- if not SETTINGS["openai_api_key"]:
119
- logger.warning("OpenAI API key not found in settings. Please enter your API key below.")
120
- openai_api_key = getpass.getpass("OpenAI API key: ")
121
- SETTINGS.update({"openai_api_key": openai_api_key})
122
- openai = OpenAI(api_key=SETTINGS["openai_api_key"])
123
-
124
- messages = [
125
- {
126
- "role": "system",
127
- "content": """
128
- You are a helpful data scientist proficient in SQL. You need to output exactly one SQL query based on
129
- the following schema and a user request. You only need to output the format with fixed selection
130
- statement that selects everything from "'table'", like `SELECT * from 'table'`
131
-
132
- Schema:
133
- im_file: string not null
134
- labels: list<item: string> not null
135
- child 0, item: string
136
- cls: list<item: int64> not null
137
- child 0, item: int64
138
- bboxes: list<item: list<item: double>> not null
139
- child 0, item: list<item: double>
140
- child 0, item: double
141
- masks: list<item: list<item: list<item: int64>>> not null
142
- child 0, item: list<item: list<item: int64>>
143
- child 0, item: list<item: int64>
144
- child 0, item: int64
145
- keypoints: list<item: list<item: list<item: double>>> not null
146
- child 0, item: list<item: list<item: double>>
147
- child 0, item: list<item: double>
148
- child 0, item: double
149
- vector: fixed_size_list<item: float>[256] not null
150
- child 0, item: float
151
-
152
- Some details about the schema:
153
- - the "labels" column contains the string values like 'person' and 'dog' for the respective objects
154
- in each image
155
- - the "cls" column contains the integer values on these classes that map them the labels
156
-
157
- Example of a correct query:
158
- request - Get all data points that contain 2 or more people and at least one dog
159
- correct query-
160
- SELECT * FROM 'table' WHERE ARRAY_LENGTH(cls) >= 2 AND ARRAY_LENGTH(FILTER(labels, x -> x = 'person')) >= 2 AND ARRAY_LENGTH(FILTER(labels, x -> x = 'dog')) >= 1;
161
- """,
162
- },
163
- {"role": "user", "content": f"{query}"},
164
- ]
165
-
166
- response = openai.chat.completions.create(model="gpt-3.5-turbo", messages=messages)
167
- return response.choices[0].message.content