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

tests/test_cli.py CHANGED
@@ -97,9 +97,12 @@ def test_mobilesam():
97
97
  # Source
98
98
  source = ASSETS / "zidane.jpg"
99
99
 
100
- # Predict a segment based on a point prompt
100
+ # Predict a segment based on a 1D point prompt and 1D labels.
101
101
  model.predict(source, points=[900, 370], labels=[1])
102
102
 
103
+ # Predict a segment based on 3D points and 2D labels (multiple points per object).
104
+ model.predict(source, points=[[[900, 370], [1000, 100]]], labels=[[1, 1]])
105
+
103
106
  # Predict a segment based on a box prompt
104
107
  model.predict(source, bboxes=[439, 437, 524, 709], save=True)
105
108
 
tests/test_cuda.py CHANGED
@@ -127,9 +127,21 @@ def test_predict_sam():
127
127
  # Run inference with bboxes prompt
128
128
  model(SOURCE, bboxes=[439, 437, 524, 709], device=0)
129
129
 
130
- # Run inference with points prompt
130
+ # Run inference with no labels
131
+ model(ASSETS / "zidane.jpg", points=[900, 370], device=0)
132
+
133
+ # Run inference with 1D points and 1D labels
131
134
  model(ASSETS / "zidane.jpg", points=[900, 370], labels=[1], device=0)
132
135
 
136
+ # Run inference with 2D points and 1D labels
137
+ model(ASSETS / "zidane.jpg", points=[[900, 370]], labels=[1], device=0)
138
+
139
+ # Run inference with multiple 2D points and 1D labels
140
+ model(ASSETS / "zidane.jpg", points=[[400, 370], [900, 370]], labels=[1, 1], device=0)
141
+
142
+ # Run inference with 3D points and 2D labels (multiple points per object)
143
+ model(ASSETS / "zidane.jpg", points=[[[900, 370], [1000, 100]]], labels=[[1, 1]], device=0)
144
+
133
145
  # Create SAMPredictor
134
146
  overrides = dict(conf=0.25, task="segment", mode="predict", imgsz=1024, model=WEIGHTS_DIR / "mobile_sam.pt")
135
147
  predictor = SAMPredictor(overrides=overrides)
ultralytics/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # Ultralytics YOLO 🚀, AGPL-3.0 license
2
2
 
3
- __version__ = "8.3.11"
3
+ __version__ = "8.3.13"
4
4
 
5
5
  import os
6
6
 
@@ -8,7 +8,6 @@ import os
8
8
  if not os.environ.get("OMP_NUM_THREADS"):
9
9
  os.environ["OMP_NUM_THREADS"] = "1" # default for reduced CPU utilization during training
10
10
 
11
- from ultralytics.data.explorer.explorer import Explorer
12
11
  from ultralytics.models import NAS, RTDETR, SAM, YOLO, FastSAM, YOLOWorld
13
12
  from ultralytics.utils import ASSETS, SETTINGS
14
13
  from ultralytics.utils.checks import check_yolo as checks
@@ -27,5 +26,4 @@ __all__ = (
27
26
  "checks",
28
27
  "download",
29
28
  "settings",
30
- "Explorer",
31
29
  )
@@ -79,14 +79,11 @@ CLI_HELP_MSG = f"""
79
79
 
80
80
  4. Export a YOLO11n classification model to ONNX format at image size 224 by 128 (no TASK required)
81
81
  yolo export model=yolo11n-cls.pt format=onnx imgsz=224,128
82
-
83
- 5. Explore your datasets using semantic search and SQL with a simple GUI powered by Ultralytics Explorer API
84
- yolo explorer data=data.yaml model=yolo11n.pt
85
82
 
86
- 6. Streamlit real-time webcam inference GUI
83
+ 5. Streamlit real-time webcam inference GUI
87
84
  yolo streamlit-predict
88
85
 
89
- 7. Run special commands:
86
+ 6. Run special commands:
90
87
  yolo help
91
88
  yolo checks
92
89
  yolo version
@@ -546,35 +543,6 @@ def handle_yolo_settings(args: List[str]) -> None:
546
543
  LOGGER.warning(f"WARNING ⚠️ settings error: '{e}'. Please see {url} for help.")
547
544
 
548
545
 
549
- def handle_explorer(args: List[str]):
550
- """
551
- Launches a graphical user interface that provides tools for interacting with and analyzing datasets using the
552
- Ultralytics Explorer API. It checks for the required 'streamlit' package and informs the user that the Explorer
553
- dashboard is loading.
554
-
555
- Args:
556
- args (List[str]): A list of optional command line arguments.
557
-
558
- Examples:
559
- ```bash
560
- yolo explorer data=data.yaml model=yolo11n.pt
561
- ```
562
-
563
- Notes:
564
- - Requires 'streamlit' package version 1.29.0 or higher.
565
- - The function does not take any arguments or return any values.
566
- - It is typically called from the command line interface using the 'yolo explorer' command.
567
- """
568
- checks.check_requirements("streamlit>=1.29.0")
569
- LOGGER.info("💡 Loading Explorer dashboard...")
570
- cmd = ["streamlit", "run", ROOT / "data/explorer/gui/dash.py", "--server.maxMessageSize", "2048"]
571
- new = dict(parse_key_value_pair(a) for a in args)
572
- check_dict_alignment(base={k: DEFAULT_CFG_DICT[k] for k in ["model", "data"]}, custom=new)
573
- for k, v in new.items():
574
- cmd += [k, v]
575
- subprocess.run(cmd)
576
-
577
-
578
546
  def handle_streamlit_inference():
579
547
  """
580
548
  Open the Ultralytics Live Inference Streamlit app for real-time object detection.
@@ -715,7 +683,6 @@ def entrypoint(debug=""):
715
683
  "login": lambda: handle_yolo_hub(args),
716
684
  "logout": lambda: handle_yolo_hub(args),
717
685
  "copy-cfg": copy_default_cfg,
718
- "explorer": lambda: handle_explorer(args[1:]),
719
686
  "streamlit-predict": lambda: handle_streamlit_inference(),
720
687
  }
721
688
  full_args_dict = {**DEFAULT_CFG_DICT, **{k: None for k in TASKS}, **{k: None for k in MODES}, **special}
@@ -14,3 +14,4 @@ up_angle: 145.0 # Workouts up_angle for counts, 145.0 is default value. You can
14
14
  down_angle: 90 # Workouts down_angle for counts, 90 is default value. You can change it for different workouts, based on position of keypoints.
15
15
  kpts: [6, 8, 10] # Keypoints for workouts monitoring, i.e. If you want to consider keypoints for pushups that have mostly values of [6, 8, 10].
16
16
  colormap: # Colormap for heatmap, Only OPENCV supported colormaps can be used. By default COLORMAP_PARULA will be used for visualization.
17
+ analytics_type: "line" # Analytics type i.e "line", "pie", "bar" or "area" charts. By default, "line" analytics will be used for processing.
@@ -960,7 +960,15 @@ class Exporter:
960
960
  LOGGER.info(f"\n{prefix} starting export with Edge TPU compiler {ver}...")
961
961
  f = str(tflite_model).replace(".tflite", "_edgetpu.tflite") # Edge TPU model
962
962
 
963
- cmd = f'edgetpu_compiler -s -d -k 10 --out_dir "{Path(f).parent}" "{tflite_model}"'
963
+ cmd = (
964
+ "edgetpu_compiler "
965
+ f'--out_dir "{Path(f).parent}" '
966
+ "--show_operations "
967
+ "--search_delegate "
968
+ "--delegate_search_step 30 "
969
+ "--timeout_sec 180 "
970
+ f'"{tflite_model}"'
971
+ )
964
972
  LOGGER.info(f"{prefix} running '{cmd}'")
965
973
  subprocess.run(cmd, shell=True)
966
974
  self._add_tflite_metadata(f)
@@ -213,11 +213,14 @@ class Predictor(BasePredictor):
213
213
  Args:
214
214
  im (torch.Tensor): Preprocessed input image tensor with shape (N, C, H, W).
215
215
  bboxes (np.ndarray | List | None): Bounding boxes in XYXY format with shape (N, 4).
216
- points (np.ndarray | List | None): Points indicating object locations with shape (N, 2), in pixels.
217
- labels (np.ndarray | List | None): Point prompt labels with shape (N,). 1 for foreground, 0 for background.
216
+ points (np.ndarray | List | None): Points indicating object locations with shape (N, 2) or (N, num_points, 2), in pixels.
217
+ labels (np.ndarray | List | None): Point prompt labels with shape (N,) or (N, num_points). 1 for foreground, 0 for background.
218
218
  masks (np.ndarray | None): Low-res masks from previous predictions with shape (N, H, W). For SAM, H=W=256.
219
219
  multimask_output (bool): Flag to return multiple masks for ambiguous prompts.
220
220
 
221
+ Raises:
222
+ AssertionError: If the number of points don't match the number of labels, in case labels were passed.
223
+
221
224
  Returns:
222
225
  (tuple): Tuple containing:
223
226
  - np.ndarray: Output masks with shape (C, H, W), where C is the number of generated masks.
@@ -232,26 +235,7 @@ class Predictor(BasePredictor):
232
235
  """
233
236
  features = self.get_im_features(im) if self.features is None else self.features
234
237
 
235
- src_shape, dst_shape = self.batch[1][0].shape[:2], im.shape[2:]
236
- r = 1.0 if self.segment_all else min(dst_shape[0] / src_shape[0], dst_shape[1] / src_shape[1])
237
- # Transform input prompts
238
- if points is not None:
239
- points = torch.as_tensor(points, dtype=torch.float32, device=self.device)
240
- points = points[None] if points.ndim == 1 else points
241
- # Assuming labels are all positive if users don't pass labels.
242
- if labels is None:
243
- labels = np.ones(points.shape[0])
244
- labels = torch.as_tensor(labels, dtype=torch.int32, device=self.device)
245
- points *= r
246
- # (N, 2) --> (N, 1, 2), (N, ) --> (N, 1)
247
- points, labels = points[:, None, :], labels[:, None]
248
- if bboxes is not None:
249
- bboxes = torch.as_tensor(bboxes, dtype=torch.float32, device=self.device)
250
- bboxes = bboxes[None] if bboxes.ndim == 1 else bboxes
251
- bboxes *= r
252
- if masks is not None:
253
- masks = torch.as_tensor(masks, dtype=torch.float32, device=self.device).unsqueeze(1)
254
-
238
+ bboxes, points, labels, masks = self._prepare_prompts(im.shape[2:], bboxes, points, labels, masks)
255
239
  points = (points, labels) if points is not None else None
256
240
  # Embed prompts
257
241
  sparse_embeddings, dense_embeddings = self.model.prompt_encoder(points=points, boxes=bboxes, masks=masks)
@@ -269,6 +253,48 @@ class Predictor(BasePredictor):
269
253
  # `d` could be 1 or 3 depends on `multimask_output`.
270
254
  return pred_masks.flatten(0, 1), pred_scores.flatten(0, 1)
271
255
 
256
+ def _prepare_prompts(self, dst_shape, bboxes=None, points=None, labels=None, masks=None):
257
+ """
258
+ Prepares and transforms the input prompts for processing based on the destination shape.
259
+
260
+ Args:
261
+ dst_shape (tuple): The target shape (height, width) for the prompts.
262
+ bboxes (np.ndarray | List | None): Bounding boxes in XYXY format with shape (N, 4).
263
+ points (np.ndarray | List | None): Points indicating object locations with shape (N, 2) or (N, num_points, 2), in pixels.
264
+ labels (np.ndarray | List | None): Point prompt labels with shape (N,) or (N, num_points). 1 for foreground, 0 for background.
265
+ masks (List | np.ndarray, Optional): Masks for the objects, where each mask is a 2D array.
266
+
267
+ Raises:
268
+ AssertionError: If the number of points don't match the number of labels, in case labels were passed.
269
+
270
+ Returns:
271
+ (tuple): A tuple containing transformed bounding boxes, points, labels, and masks.
272
+ """
273
+ src_shape = self.batch[1][0].shape[:2]
274
+ r = 1.0 if self.segment_all else min(dst_shape[0] / src_shape[0], dst_shape[1] / src_shape[1])
275
+ # Transform input prompts
276
+ if points is not None:
277
+ points = torch.as_tensor(points, dtype=torch.float32, device=self.device)
278
+ points = points[None] if points.ndim == 1 else points
279
+ # Assuming labels are all positive if users don't pass labels.
280
+ if labels is None:
281
+ labels = np.ones(points.shape[:-1])
282
+ labels = torch.as_tensor(labels, dtype=torch.int32, device=self.device)
283
+ assert (
284
+ points.shape[-2] == labels.shape[-1]
285
+ ), f"Number of points {points.shape[-2]} should match number of labels {labels.shape[-1]}."
286
+ points *= r
287
+ if points.ndim == 2:
288
+ # (N, 2) --> (N, 1, 2), (N, ) --> (N, 1)
289
+ points, labels = points[:, None, :], labels[:, None]
290
+ if bboxes is not None:
291
+ bboxes = torch.as_tensor(bboxes, dtype=torch.float32, device=self.device)
292
+ bboxes = bboxes[None] if bboxes.ndim == 1 else bboxes
293
+ bboxes *= r
294
+ if masks is not None:
295
+ masks = torch.as_tensor(masks, dtype=torch.float32, device=self.device).unsqueeze(1)
296
+ return bboxes, points, labels, masks
297
+
272
298
  def generate(
273
299
  self,
274
300
  im,
@@ -686,34 +712,7 @@ class SAM2Predictor(Predictor):
686
712
  """
687
713
  features = self.get_im_features(im) if self.features is None else self.features
688
714
 
689
- src_shape, dst_shape = self.batch[1][0].shape[:2], im.shape[2:]
690
- r = 1.0 if self.segment_all else min(dst_shape[0] / src_shape[0], dst_shape[1] / src_shape[1])
691
- # Transform input prompts
692
- if points is not None:
693
- points = torch.as_tensor(points, dtype=torch.float32, device=self.device)
694
- points = points[None] if points.ndim == 1 else points
695
- # Assuming labels are all positive if users don't pass labels.
696
- if labels is None:
697
- labels = torch.ones(points.shape[0])
698
- labels = torch.as_tensor(labels, dtype=torch.int32, device=self.device)
699
- points *= r
700
- # (N, 2) --> (N, 1, 2), (N, ) --> (N, 1)
701
- points, labels = points[:, None], labels[:, None]
702
- if bboxes is not None:
703
- bboxes = torch.as_tensor(bboxes, dtype=torch.float32, device=self.device)
704
- bboxes = bboxes[None] if bboxes.ndim == 1 else bboxes
705
- bboxes = bboxes.view(-1, 2, 2) * r
706
- bbox_labels = torch.tensor([[2, 3]], dtype=torch.int32, device=bboxes.device).expand(len(bboxes), -1)
707
- # NOTE: merge "boxes" and "points" into a single "points" input
708
- # (where boxes are added at the beginning) to model.sam_prompt_encoder
709
- if points is not None:
710
- points = torch.cat([bboxes, points], dim=1)
711
- labels = torch.cat([bbox_labels, labels], dim=1)
712
- else:
713
- points, labels = bboxes, bbox_labels
714
- if masks is not None:
715
- masks = torch.as_tensor(masks, dtype=torch.float32, device=self.device).unsqueeze(1)
716
-
715
+ bboxes, points, labels, masks = self._prepare_prompts(im.shape[2:], bboxes, points, labels, masks)
717
716
  points = (points, labels) if points is not None else None
718
717
 
719
718
  sparse_embeddings, dense_embeddings = self.model.sam_prompt_encoder(
@@ -737,6 +736,36 @@ class SAM2Predictor(Predictor):
737
736
  # `d` could be 1 or 3 depends on `multimask_output`.
738
737
  return pred_masks.flatten(0, 1), pred_scores.flatten(0, 1)
739
738
 
739
+ def _prepare_prompts(self, dst_shape, bboxes=None, points=None, labels=None, masks=None):
740
+ """
741
+ Prepares and transforms the input prompts for processing based on the destination shape.
742
+
743
+ Args:
744
+ dst_shape (tuple): The target shape (height, width) for the prompts.
745
+ bboxes (np.ndarray | List | None): Bounding boxes in XYXY format with shape (N, 4).
746
+ points (np.ndarray | List | None): Points indicating object locations with shape (N, 2) or (N, num_points, 2), in pixels.
747
+ labels (np.ndarray | List | None): Point prompt labels with shape (N,) or (N, num_points). 1 for foreground, 0 for background.
748
+ masks (List | np.ndarray, Optional): Masks for the objects, where each mask is a 2D array.
749
+
750
+ Raises:
751
+ AssertionError: If the number of points don't match the number of labels, in case labels were passed.
752
+
753
+ Returns:
754
+ (tuple): A tuple containing transformed bounding boxes, points, labels, and masks.
755
+ """
756
+ bboxes, points, labels, masks = super()._prepare_prompts(dst_shape, bboxes, points, labels, masks)
757
+ if bboxes is not None:
758
+ bboxes = bboxes.view(-1, 2, 2)
759
+ bbox_labels = torch.tensor([[2, 3]], dtype=torch.int32, device=bboxes.device).expand(len(bboxes), -1)
760
+ # NOTE: merge "boxes" and "points" into a single "points" input
761
+ # (where boxes are added at the beginning) to model.sam_prompt_encoder
762
+ if points is not None:
763
+ points = torch.cat([bboxes, points], dim=1)
764
+ labels = torch.cat([bbox_labels, labels], dim=1)
765
+ else:
766
+ points, labels = bboxes, bbox_labels
767
+ return bboxes, points, labels, masks
768
+
740
769
  def set_image(self, image):
741
770
  """
742
771
  Preprocesses and sets a single image for inference using the SAM2 model.
@@ -8,7 +8,7 @@ from ultralytics.data import ClassificationDataset, build_dataloader
8
8
  from ultralytics.engine.trainer import BaseTrainer
9
9
  from ultralytics.models import yolo
10
10
  from ultralytics.nn.tasks import ClassificationModel
11
- from ultralytics.utils import DEFAULT_CFG, LOGGER, RANK, colorstr
11
+ from ultralytics.utils import DEFAULT_CFG, LOGGER, RANK
12
12
  from ultralytics.utils.plotting import plot_images, plot_results
13
13
  from ultralytics.utils.torch_utils import is_parallel, strip_optimizer, torch_distributed_zero_first
14
14
 
@@ -141,7 +141,6 @@ class ClassificationTrainer(BaseTrainer):
141
141
  self.metrics = self.validator(model=f)
142
142
  self.metrics.pop("fitness", None)
143
143
  self.run_callbacks("on_fit_epoch_end")
144
- LOGGER.info(f"Results saved to {colorstr('bold', self.save_dir)}")
145
144
 
146
145
  def plot_training_samples(self, batch, ni):
147
146
  """Plots training samples with their annotations."""