ultralytics 8.3.190__py3-none-any.whl → 8.3.191__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.
Files changed (102) hide show
  1. tests/test_cuda.py +6 -5
  2. tests/test_exports.py +1 -6
  3. tests/test_python.py +1 -4
  4. tests/test_solutions.py +1 -1
  5. ultralytics/__init__.py +1 -1
  6. ultralytics/cfg/__init__.py +16 -14
  7. ultralytics/cfg/datasets/VisDrone.yaml +4 -4
  8. ultralytics/data/annotator.py +6 -6
  9. ultralytics/data/augment.py +53 -51
  10. ultralytics/data/base.py +15 -13
  11. ultralytics/data/build.py +7 -4
  12. ultralytics/data/converter.py +9 -10
  13. ultralytics/data/dataset.py +24 -22
  14. ultralytics/data/loaders.py +13 -11
  15. ultralytics/data/split.py +4 -3
  16. ultralytics/data/split_dota.py +14 -12
  17. ultralytics/data/utils.py +29 -23
  18. ultralytics/engine/exporter.py +2 -2
  19. ultralytics/engine/model.py +16 -14
  20. ultralytics/engine/predictor.py +8 -6
  21. ultralytics/engine/results.py +54 -52
  22. ultralytics/engine/trainer.py +7 -2
  23. ultralytics/engine/tuner.py +4 -3
  24. ultralytics/hub/google/__init__.py +7 -6
  25. ultralytics/hub/session.py +8 -6
  26. ultralytics/hub/utils.py +3 -4
  27. ultralytics/models/fastsam/model.py +8 -6
  28. ultralytics/models/nas/model.py +5 -3
  29. ultralytics/models/rtdetr/train.py +4 -3
  30. ultralytics/models/rtdetr/val.py +6 -4
  31. ultralytics/models/sam/amg.py +13 -10
  32. ultralytics/models/sam/model.py +3 -2
  33. ultralytics/models/sam/modules/blocks.py +21 -21
  34. ultralytics/models/sam/modules/decoders.py +11 -11
  35. ultralytics/models/sam/modules/encoders.py +25 -25
  36. ultralytics/models/sam/modules/memory_attention.py +9 -8
  37. ultralytics/models/sam/modules/sam.py +8 -10
  38. ultralytics/models/sam/modules/tiny_encoder.py +21 -20
  39. ultralytics/models/sam/modules/transformer.py +6 -5
  40. ultralytics/models/sam/modules/utils.py +7 -5
  41. ultralytics/models/sam/predict.py +32 -31
  42. ultralytics/models/utils/loss.py +29 -27
  43. ultralytics/models/utils/ops.py +10 -8
  44. ultralytics/models/yolo/classify/train.py +7 -5
  45. ultralytics/models/yolo/classify/val.py +10 -8
  46. ultralytics/models/yolo/detect/predict.py +1 -1
  47. ultralytics/models/yolo/detect/train.py +8 -6
  48. ultralytics/models/yolo/detect/val.py +21 -19
  49. ultralytics/models/yolo/model.py +14 -14
  50. ultralytics/models/yolo/obb/train.py +5 -3
  51. ultralytics/models/yolo/obb/val.py +11 -9
  52. ultralytics/models/yolo/pose/train.py +7 -5
  53. ultralytics/models/yolo/pose/val.py +11 -9
  54. ultralytics/models/yolo/segment/train.py +4 -5
  55. ultralytics/models/yolo/segment/val.py +12 -10
  56. ultralytics/models/yolo/world/train.py +9 -7
  57. ultralytics/models/yolo/yoloe/train.py +7 -6
  58. ultralytics/models/yolo/yoloe/val.py +10 -8
  59. ultralytics/nn/autobackend.py +17 -19
  60. ultralytics/nn/modules/block.py +12 -12
  61. ultralytics/nn/modules/conv.py +4 -3
  62. ultralytics/nn/modules/head.py +41 -37
  63. ultralytics/nn/modules/transformer.py +22 -21
  64. ultralytics/nn/tasks.py +2 -2
  65. ultralytics/nn/text_model.py +6 -5
  66. ultralytics/solutions/analytics.py +7 -5
  67. ultralytics/solutions/config.py +12 -10
  68. ultralytics/solutions/distance_calculation.py +3 -3
  69. ultralytics/solutions/heatmap.py +4 -2
  70. ultralytics/solutions/object_counter.py +5 -3
  71. ultralytics/solutions/parking_management.py +4 -2
  72. ultralytics/solutions/region_counter.py +7 -5
  73. ultralytics/solutions/similarity_search.py +5 -3
  74. ultralytics/solutions/solutions.py +38 -36
  75. ultralytics/solutions/streamlit_inference.py +8 -7
  76. ultralytics/trackers/bot_sort.py +11 -9
  77. ultralytics/trackers/byte_tracker.py +17 -15
  78. ultralytics/trackers/utils/gmc.py +4 -3
  79. ultralytics/utils/__init__.py +16 -88
  80. ultralytics/utils/autobatch.py +3 -2
  81. ultralytics/utils/autodevice.py +10 -10
  82. ultralytics/utils/benchmarks.py +11 -10
  83. ultralytics/utils/callbacks/comet.py +9 -9
  84. ultralytics/utils/checks.py +17 -26
  85. ultralytics/utils/export.py +12 -11
  86. ultralytics/utils/files.py +8 -7
  87. ultralytics/utils/git.py +139 -0
  88. ultralytics/utils/instance.py +8 -7
  89. ultralytics/utils/loss.py +15 -13
  90. ultralytics/utils/metrics.py +62 -62
  91. ultralytics/utils/ops.py +3 -2
  92. ultralytics/utils/patches.py +6 -4
  93. ultralytics/utils/plotting.py +18 -16
  94. ultralytics/utils/torch_utils.py +4 -2
  95. ultralytics/utils/tqdm.py +15 -12
  96. ultralytics/utils/triton.py +3 -2
  97. {ultralytics-8.3.190.dist-info → ultralytics-8.3.191.dist-info}/METADATA +1 -1
  98. {ultralytics-8.3.190.dist-info → ultralytics-8.3.191.dist-info}/RECORD +102 -101
  99. {ultralytics-8.3.190.dist-info → ultralytics-8.3.191.dist-info}/WHEEL +0 -0
  100. {ultralytics-8.3.190.dist-info → ultralytics-8.3.191.dist-info}/entry_points.txt +0 -0
  101. {ultralytics-8.3.190.dist-info → ultralytics-8.3.191.dist-info}/licenses/LICENSE +0 -0
  102. {ultralytics-8.3.190.dist-info → ultralytics-8.3.191.dist-info}/top_level.txt +0 -0
ultralytics/data/utils.py CHANGED
@@ -1,5 +1,7 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import json
4
6
  import os
5
7
  import random
@@ -9,7 +11,7 @@ import zipfile
9
11
  from multiprocessing.pool import ThreadPool
10
12
  from pathlib import Path
11
13
  from tarfile import is_tarfile
12
- from typing import Any, Dict, List, Tuple, Union
14
+ from typing import Any
13
15
 
14
16
  import cv2
15
17
  import numpy as np
@@ -39,14 +41,14 @@ VID_FORMATS = {"asf", "avi", "gif", "m4v", "mkv", "mov", "mp4", "mpeg", "mpg", "
39
41
  FORMATS_HELP_MSG = f"Supported formats are:\nimages: {IMG_FORMATS}\nvideos: {VID_FORMATS}"
40
42
 
41
43
 
42
- def img2label_paths(img_paths: List[str]) -> List[str]:
44
+ def img2label_paths(img_paths: list[str]) -> list[str]:
43
45
  """Convert image paths to label paths by replacing 'images' with 'labels' and extension with '.txt'."""
44
46
  sa, sb = f"{os.sep}images{os.sep}", f"{os.sep}labels{os.sep}" # /images/, /labels/ substrings
45
47
  return [sb.join(x.rsplit(sa, 1)).rsplit(".", 1)[0] + ".txt" for x in img_paths]
46
48
 
47
49
 
48
50
  def check_file_speeds(
49
- files: List[str], threshold_ms: float = 10, threshold_mb: float = 50, max_files: int = 5, prefix: str = ""
51
+ files: list[str], threshold_ms: float = 10, threshold_mb: float = 50, max_files: int = 5, prefix: str = ""
50
52
  ):
51
53
  """
52
54
  Check dataset file access speed and provide performance feedback.
@@ -66,7 +68,7 @@ def check_file_speeds(
66
68
  >>> image_files = list(Path("dataset/images").glob("*.jpg"))
67
69
  >>> check_file_speeds(image_files, threshold_ms=15)
68
70
  """
69
- if not files or len(files) == 0:
71
+ if not files:
70
72
  LOGGER.warning(f"{prefix}Image speed checks: No files to check")
71
73
  return
72
74
 
@@ -123,7 +125,7 @@ def check_file_speeds(
123
125
  )
124
126
 
125
127
 
126
- def get_hash(paths: List[str]) -> str:
128
+ def get_hash(paths: list[str]) -> str:
127
129
  """Return a single hash value of a list of paths (files or dirs)."""
128
130
  size = 0
129
131
  for p in paths:
@@ -136,7 +138,7 @@ def get_hash(paths: List[str]) -> str:
136
138
  return h.hexdigest() # return hash
137
139
 
138
140
 
139
- def exif_size(img: Image.Image) -> Tuple[int, int]:
141
+ def exif_size(img: Image.Image) -> tuple[int, int]:
140
142
  """Return exif-corrected PIL size."""
141
143
  s = img.size # (width, height)
142
144
  if img.format == "JPEG": # only support JPEG images
@@ -150,7 +152,7 @@ def exif_size(img: Image.Image) -> Tuple[int, int]:
150
152
  return s
151
153
 
152
154
 
153
- def verify_image(args: Tuple) -> Tuple:
155
+ def verify_image(args: tuple) -> tuple:
154
156
  """Verify one image."""
155
157
  (im_file, cls), prefix = args
156
158
  # Number (found, corrupt), message
@@ -175,7 +177,7 @@ def verify_image(args: Tuple) -> Tuple:
175
177
  return (im_file, cls), nf, nc, msg
176
178
 
177
179
 
178
- def verify_image_label(args: Tuple) -> List:
180
+ def verify_image_label(args: tuple) -> list:
179
181
  """Verify one image-label pair."""
180
182
  im_file, lb_file, prefix, keypoint, num_cls, nkpt, ndim, single_cls = args
181
183
  # Number (missing, found, empty, corrupt), message, segments, keypoints
@@ -247,7 +249,7 @@ def verify_image_label(args: Tuple) -> List:
247
249
  return [None, None, None, None, None, nm, nf, ne, nc, msg]
248
250
 
249
251
 
250
- def visualize_image_annotations(image_path: str, txt_path: str, label_map: Dict[int, str]):
252
+ def visualize_image_annotations(image_path: str, txt_path: str, label_map: dict[int, str]):
251
253
  """
252
254
  Visualize YOLO annotations (bounding boxes and class labels) on an image.
253
255
 
@@ -292,7 +294,7 @@ def visualize_image_annotations(image_path: str, txt_path: str, label_map: Dict[
292
294
 
293
295
 
294
296
  def polygon2mask(
295
- imgsz: Tuple[int, int], polygons: List[np.ndarray], color: int = 1, downsample_ratio: int = 1
297
+ imgsz: tuple[int, int], polygons: list[np.ndarray], color: int = 1, downsample_ratio: int = 1
296
298
  ) -> np.ndarray:
297
299
  """
298
300
  Convert a list of polygons to a binary mask of the specified image size.
@@ -317,7 +319,7 @@ def polygon2mask(
317
319
 
318
320
 
319
321
  def polygons2masks(
320
- imgsz: Tuple[int, int], polygons: List[np.ndarray], color: int, downsample_ratio: int = 1
322
+ imgsz: tuple[int, int], polygons: list[np.ndarray], color: int, downsample_ratio: int = 1
321
323
  ) -> np.ndarray:
322
324
  """
323
325
  Convert a list of polygons to a set of binary masks of the specified image size.
@@ -336,8 +338,8 @@ def polygons2masks(
336
338
 
337
339
 
338
340
  def polygons2masks_overlap(
339
- imgsz: Tuple[int, int], segments: List[np.ndarray], downsample_ratio: int = 1
340
- ) -> Tuple[np.ndarray, np.ndarray]:
341
+ imgsz: tuple[int, int], segments: list[np.ndarray], downsample_ratio: int = 1
342
+ ) -> tuple[np.ndarray, np.ndarray]:
341
343
  """Return a (640, 640) overlap mask."""
342
344
  masks = np.zeros(
343
345
  (imgsz[0] // downsample_ratio, imgsz[1] // downsample_ratio),
@@ -345,8 +347,13 @@ def polygons2masks_overlap(
345
347
  )
346
348
  areas = []
347
349
  ms = []
348
- for si in range(len(segments)):
349
- mask = polygon2mask(imgsz, [segments[si].reshape(-1)], downsample_ratio=downsample_ratio, color=1)
350
+ for segment in segments:
351
+ mask = polygon2mask(
352
+ imgsz,
353
+ [segment.reshape(-1)],
354
+ downsample_ratio=downsample_ratio,
355
+ color=1,
356
+ )
350
357
  ms.append(mask.astype(masks.dtype))
351
358
  areas.append(mask.sum())
352
359
  areas = np.asarray(areas)
@@ -380,7 +387,7 @@ def find_dataset_yaml(path: Path) -> Path:
380
387
  return files[0]
381
388
 
382
389
 
383
- def check_det_dataset(dataset: str, autodownload: bool = True) -> Dict[str, Any]:
390
+ def check_det_dataset(dataset: str, autodownload: bool = True) -> dict[str, Any]:
384
391
  """
385
392
  Download, verify, and/or unzip a dataset if not found locally.
386
393
 
@@ -475,7 +482,7 @@ def check_det_dataset(dataset: str, autodownload: bool = True) -> Dict[str, Any]
475
482
  return data # dictionary
476
483
 
477
484
 
478
- def check_cls_dataset(dataset: Union[str, Path], split: str = "") -> Dict[str, Any]:
485
+ def check_cls_dataset(dataset: str | Path, split: str = "") -> dict[str, Any]:
479
486
  """
480
487
  Check a classification dataset such as Imagenet.
481
488
 
@@ -517,8 +524,7 @@ def check_cls_dataset(dataset: Union[str, Path], split: str = "") -> Dict[str, A
517
524
  train_set = data_dir / "train"
518
525
  if not train_set.is_dir():
519
526
  LOGGER.warning(f"Dataset 'split=train' not found at {train_set}")
520
- image_files = list(data_dir.rglob("*.jpg")) + list(data_dir.rglob("*.png"))
521
- if image_files:
527
+ if image_files := list(data_dir.rglob("*.jpg")) + list(data_dir.rglob("*.png")):
522
528
  from ultralytics.data.split import split_classify_dataset
523
529
 
524
530
  LOGGER.info(f"Found {len(image_files)} images in subdirectories. Attempting to split...")
@@ -632,7 +638,7 @@ class HUBDatasetStats:
632
638
  self.data = data
633
639
 
634
640
  @staticmethod
635
- def _unzip(path: Path) -> Tuple[bool, str, Path]:
641
+ def _unzip(path: Path) -> tuple[bool, str, Path]:
636
642
  """Unzip data.zip."""
637
643
  if not str(path).endswith(".zip"): # path is data.yaml
638
644
  return False, None, path
@@ -646,7 +652,7 @@ class HUBDatasetStats:
646
652
  """Save a compressed image for HUB previews."""
647
653
  compress_one_image(f, self.im_dir / Path(f).name) # save to dataset-hub
648
654
 
649
- def get_json(self, save: bool = False, verbose: bool = False) -> Dict:
655
+ def get_json(self, save: bool = False, verbose: bool = False) -> dict:
650
656
  """Return dataset JSON for Ultralytics HUB."""
651
657
 
652
658
  def _round(labels):
@@ -773,7 +779,7 @@ def compress_one_image(f: str, f_new: str = None, max_dim: int = 1920, quality:
773
779
  cv2.imwrite(str(f_new or f), im)
774
780
 
775
781
 
776
- def load_dataset_cache_file(path: Path) -> Dict:
782
+ def load_dataset_cache_file(path: Path) -> dict:
777
783
  """Load an Ultralytics *.cache dictionary from path."""
778
784
  import gc
779
785
 
@@ -783,7 +789,7 @@ def load_dataset_cache_file(path: Path) -> Dict:
783
789
  return cache
784
790
 
785
791
 
786
- def save_dataset_cache_file(prefix: str, path: Path, x: Dict, version: str):
792
+ def save_dataset_cache_file(prefix: str, path: Path, x: dict, version: str):
787
793
  """Save an Ultralytics dataset *.cache dictionary x to path."""
788
794
  x["version"] = version # add cache version
789
795
  if is_dir_writeable(path.parent):
@@ -349,7 +349,7 @@ class Exporter:
349
349
  assert not getattr(model, "end2end", False), "TFLite INT8 export not supported for end2end models."
350
350
  if self.args.nms:
351
351
  assert not isinstance(model, ClassificationModel), "'nms=True' is not valid for classification models."
352
- assert not (tflite and ARM64 and LINUX), "TFLite export with NMS unsupported on ARM64 Linux"
352
+ assert not tflite or not ARM64 or not LINUX, "TFLite export with NMS unsupported on ARM64 Linux"
353
353
  if getattr(model, "end2end", False):
354
354
  LOGGER.warning("'nms=True' is not available for end2end models. Forcing 'nms=False'.")
355
355
  self.args.nms = False
@@ -436,7 +436,7 @@ class Exporter:
436
436
 
437
437
  y = None
438
438
  for _ in range(2): # dry runs
439
- y = NMSModel(model, self.args)(im) if self.args.nms and not (coreml or imx) else model(im)
439
+ y = NMSModel(model, self.args)(im) if self.args.nms and not coreml and not imx else model(im)
440
440
  if self.args.half and onnx and self.device.type != "cpu":
441
441
  im, model = im.half(), model.half() # to FP16
442
442
 
@@ -1,8 +1,10 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import inspect
4
6
  from pathlib import Path
5
- from typing import Any, Dict, List, Union
7
+ from typing import Any
6
8
 
7
9
  import numpy as np
8
10
  import torch
@@ -79,7 +81,7 @@ class Model(torch.nn.Module):
79
81
 
80
82
  def __init__(
81
83
  self,
82
- model: Union[str, Path, "Model"] = "yolo11n.pt",
84
+ model: str | Path | Model = "yolo11n.pt",
83
85
  task: str = None,
84
86
  verbose: bool = False,
85
87
  ) -> None:
@@ -155,7 +157,7 @@ class Model(torch.nn.Module):
155
157
 
156
158
  def __call__(
157
159
  self,
158
- source: Union[str, Path, int, Image.Image, list, tuple, np.ndarray, torch.Tensor] = None,
160
+ source: str | Path | int | Image.Image | list | tuple | np.ndarray | torch.Tensor = None,
159
161
  stream: bool = False,
160
162
  **kwargs: Any,
161
163
  ) -> list:
@@ -333,7 +335,7 @@ class Model(torch.nn.Module):
333
335
  f"argument directly in your inference command, i.e. 'model.predict(source=..., device=0)'"
334
336
  )
335
337
 
336
- def reset_weights(self) -> "Model":
338
+ def reset_weights(self) -> Model:
337
339
  """
338
340
  Reset the model's weights to their initial state.
339
341
 
@@ -359,7 +361,7 @@ class Model(torch.nn.Module):
359
361
  p.requires_grad = True
360
362
  return self
361
363
 
362
- def load(self, weights: Union[str, Path] = "yolo11n.pt") -> "Model":
364
+ def load(self, weights: str | Path = "yolo11n.pt") -> Model:
363
365
  """
364
366
  Load parameters from the specified weights file into the model.
365
367
 
@@ -387,7 +389,7 @@ class Model(torch.nn.Module):
387
389
  self.model.load(weights)
388
390
  return self
389
391
 
390
- def save(self, filename: Union[str, Path] = "saved_model.pt") -> None:
392
+ def save(self, filename: str | Path = "saved_model.pt") -> None:
391
393
  """
392
394
  Save the current model state to a file.
393
395
 
@@ -464,7 +466,7 @@ class Model(torch.nn.Module):
464
466
 
465
467
  def embed(
466
468
  self,
467
- source: Union[str, Path, int, list, tuple, np.ndarray, torch.Tensor] = None,
469
+ source: str | Path | int | list | tuple | np.ndarray | torch.Tensor = None,
468
470
  stream: bool = False,
469
471
  **kwargs: Any,
470
472
  ) -> list:
@@ -495,11 +497,11 @@ class Model(torch.nn.Module):
495
497
 
496
498
  def predict(
497
499
  self,
498
- source: Union[str, Path, int, Image.Image, list, tuple, np.ndarray, torch.Tensor] = None,
500
+ source: str | Path | int | Image.Image | list | tuple | np.ndarray | torch.Tensor = None,
499
501
  stream: bool = False,
500
502
  predictor=None,
501
503
  **kwargs: Any,
502
- ) -> List[Results]:
504
+ ) -> list[Results]:
503
505
  """
504
506
  Perform predictions on the given image source using the YOLO model.
505
507
 
@@ -556,11 +558,11 @@ class Model(torch.nn.Module):
556
558
 
557
559
  def track(
558
560
  self,
559
- source: Union[str, Path, int, list, tuple, np.ndarray, torch.Tensor] = None,
561
+ source: str | Path | int | list | tuple | np.ndarray | torch.Tensor = None,
560
562
  stream: bool = False,
561
563
  persist: bool = False,
562
564
  **kwargs: Any,
563
- ) -> List[Results]:
565
+ ) -> list[Results]:
564
566
  """
565
567
  Conduct object tracking on the specified input source using the registered trackers.
566
568
 
@@ -853,7 +855,7 @@ class Model(torch.nn.Module):
853
855
  args = {**self.overrides, **custom, **kwargs, "mode": "train"} # highest priority args on the right
854
856
  return Tuner(args=args, _callbacks=self.callbacks)(model=self, iterations=iterations)
855
857
 
856
- def _apply(self, fn) -> "Model":
858
+ def _apply(self, fn) -> Model:
857
859
  """
858
860
  Apply a function to model tensors that are not parameters or registered buffers.
859
861
 
@@ -882,7 +884,7 @@ class Model(torch.nn.Module):
882
884
  return self
883
885
 
884
886
  @property
885
- def names(self) -> Dict[int, str]:
887
+ def names(self) -> dict[int, str]:
886
888
  """
887
889
  Retrieve the class names associated with the loaded model.
888
890
 
@@ -1036,7 +1038,7 @@ class Model(torch.nn.Module):
1036
1038
  self.callbacks[event] = [callbacks.default_callbacks[event][0]]
1037
1039
 
1038
1040
  @staticmethod
1039
- def _reset_ckpt_args(args: Dict[str, Any]) -> Dict[str, Any]:
1041
+ def _reset_ckpt_args(args: dict[str, Any]) -> dict[str, Any]:
1040
1042
  """
1041
1043
  Reset specific arguments when loading a PyTorch model checkpoint.
1042
1044
 
@@ -32,11 +32,13 @@ Usage - formats:
32
32
  yolo11n_rknn_model # Rockchip RKNN
33
33
  """
34
34
 
35
+ from __future__ import annotations
36
+
35
37
  import platform
36
38
  import re
37
39
  import threading
38
40
  from pathlib import Path
39
- from typing import Any, Dict, List, Optional, Union
41
+ from typing import Any
40
42
 
41
43
  import cv2
42
44
  import numpy as np
@@ -109,8 +111,8 @@ class BasePredictor:
109
111
  def __init__(
110
112
  self,
111
113
  cfg=DEFAULT_CFG,
112
- overrides: Optional[Dict[str, Any]] = None,
113
- _callbacks: Optional[Dict[str, List[callable]]] = None,
114
+ overrides: dict[str, Any] | None = None,
115
+ _callbacks: dict[str, list[callable]] | None = None,
114
116
  ):
115
117
  """
116
118
  Initialize the BasePredictor class.
@@ -147,7 +149,7 @@ class BasePredictor:
147
149
  self._lock = threading.Lock() # for automatic thread-safe inference
148
150
  callbacks.add_integration_callbacks(self)
149
151
 
150
- def preprocess(self, im: Union[torch.Tensor, List[np.ndarray]]) -> torch.Tensor:
152
+ def preprocess(self, im: torch.Tensor | list[np.ndarray]) -> torch.Tensor:
151
153
  """
152
154
  Prepare input image before inference.
153
155
 
@@ -181,7 +183,7 @@ class BasePredictor:
181
183
  )
182
184
  return self.model(im, augment=self.args.augment, visualize=visualize, embed=self.args.embed, *args, **kwargs)
183
185
 
184
- def pre_transform(self, im: List[np.ndarray]) -> List[np.ndarray]:
186
+ def pre_transform(self, im: list[np.ndarray]) -> list[np.ndarray]:
185
187
  """
186
188
  Pre-transform input image before inference.
187
189
 
@@ -404,7 +406,7 @@ class BasePredictor:
404
406
  self.args.imgsz = self.model.imgsz # reuse imgsz from export metadata
405
407
  self.model.eval()
406
408
 
407
- def write_results(self, i: int, p: Path, im: torch.Tensor, s: List[str]) -> str:
409
+ def write_results(self, i: int, p: Path, im: torch.Tensor, s: list[str]) -> str:
408
410
  """
409
411
  Write inference results to a file or directory.
410
412