ultralytics 8.2.81__py3-none-any.whl → 8.2.83__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 (97) hide show
  1. tests/test_solutions.py +0 -4
  2. ultralytics/__init__.py +1 -1
  3. ultralytics/cfg/__init__.py +21 -21
  4. ultralytics/data/annotator.py +1 -1
  5. ultralytics/data/augment.py +58 -58
  6. ultralytics/data/base.py +3 -3
  7. ultralytics/data/converter.py +7 -8
  8. ultralytics/data/explorer/explorer.py +7 -23
  9. ultralytics/data/loaders.py +2 -2
  10. ultralytics/data/split_dota.py +11 -3
  11. ultralytics/data/utils.py +6 -10
  12. ultralytics/engine/exporter.py +2 -4
  13. ultralytics/engine/model.py +47 -47
  14. ultralytics/engine/predictor.py +1 -1
  15. ultralytics/engine/results.py +28 -28
  16. ultralytics/engine/trainer.py +11 -8
  17. ultralytics/engine/tuner.py +7 -8
  18. ultralytics/engine/validator.py +3 -5
  19. ultralytics/hub/__init__.py +5 -5
  20. ultralytics/hub/auth.py +6 -2
  21. ultralytics/hub/session.py +3 -5
  22. ultralytics/models/fastsam/model.py +13 -10
  23. ultralytics/models/fastsam/predict.py +2 -2
  24. ultralytics/models/fastsam/utils.py +0 -1
  25. ultralytics/models/nas/model.py +4 -4
  26. ultralytics/models/nas/predict.py +1 -2
  27. ultralytics/models/nas/val.py +1 -1
  28. ultralytics/models/rtdetr/predict.py +1 -1
  29. ultralytics/models/rtdetr/train.py +1 -1
  30. ultralytics/models/rtdetr/val.py +1 -1
  31. ultralytics/models/sam/model.py +11 -11
  32. ultralytics/models/sam/modules/decoders.py +7 -4
  33. ultralytics/models/sam/modules/sam.py +9 -1
  34. ultralytics/models/sam/modules/tiny_encoder.py +1 -1
  35. ultralytics/models/sam/modules/transformer.py +0 -2
  36. ultralytics/models/sam/modules/utils.py +1 -1
  37. ultralytics/models/sam/predict.py +10 -10
  38. ultralytics/models/utils/loss.py +29 -17
  39. ultralytics/models/utils/ops.py +1 -5
  40. ultralytics/models/yolo/classify/predict.py +1 -1
  41. ultralytics/models/yolo/classify/train.py +1 -1
  42. ultralytics/models/yolo/classify/val.py +1 -1
  43. ultralytics/models/yolo/detect/predict.py +1 -1
  44. ultralytics/models/yolo/detect/train.py +1 -1
  45. ultralytics/models/yolo/detect/val.py +1 -1
  46. ultralytics/models/yolo/model.py +6 -2
  47. ultralytics/models/yolo/obb/predict.py +1 -1
  48. ultralytics/models/yolo/obb/train.py +1 -1
  49. ultralytics/models/yolo/obb/val.py +2 -2
  50. ultralytics/models/yolo/pose/predict.py +1 -1
  51. ultralytics/models/yolo/pose/train.py +1 -1
  52. ultralytics/models/yolo/pose/val.py +1 -1
  53. ultralytics/models/yolo/segment/predict.py +1 -1
  54. ultralytics/models/yolo/segment/train.py +1 -1
  55. ultralytics/models/yolo/segment/val.py +1 -1
  56. ultralytics/models/yolo/world/train.py +1 -1
  57. ultralytics/nn/autobackend.py +2 -2
  58. ultralytics/nn/modules/__init__.py +2 -2
  59. ultralytics/nn/modules/block.py +8 -20
  60. ultralytics/nn/modules/conv.py +1 -3
  61. ultralytics/nn/modules/head.py +16 -31
  62. ultralytics/nn/modules/transformer.py +0 -1
  63. ultralytics/nn/modules/utils.py +0 -1
  64. ultralytics/nn/tasks.py +11 -9
  65. ultralytics/solutions/__init__.py +1 -0
  66. ultralytics/solutions/ai_gym.py +0 -2
  67. ultralytics/solutions/analytics.py +1 -6
  68. ultralytics/solutions/heatmap.py +0 -1
  69. ultralytics/solutions/object_counter.py +0 -2
  70. ultralytics/solutions/queue_management.py +0 -2
  71. ultralytics/trackers/basetrack.py +1 -1
  72. ultralytics/trackers/byte_tracker.py +2 -2
  73. ultralytics/trackers/utils/gmc.py +5 -5
  74. ultralytics/trackers/utils/kalman_filter.py +1 -1
  75. ultralytics/trackers/utils/matching.py +1 -5
  76. ultralytics/utils/__init__.py +137 -24
  77. ultralytics/utils/autobatch.py +7 -4
  78. ultralytics/utils/benchmarks.py +6 -14
  79. ultralytics/utils/callbacks/base.py +0 -1
  80. ultralytics/utils/callbacks/comet.py +0 -1
  81. ultralytics/utils/callbacks/tensorboard.py +0 -1
  82. ultralytics/utils/checks.py +15 -18
  83. ultralytics/utils/downloads.py +6 -7
  84. ultralytics/utils/files.py +3 -4
  85. ultralytics/utils/instance.py +17 -7
  86. ultralytics/utils/metrics.py +16 -16
  87. ultralytics/utils/ops.py +8 -8
  88. ultralytics/utils/plotting.py +25 -35
  89. ultralytics/utils/tal.py +27 -18
  90. ultralytics/utils/torch_utils.py +12 -13
  91. ultralytics/utils/tuner.py +2 -3
  92. {ultralytics-8.2.81.dist-info → ultralytics-8.2.83.dist-info}/METADATA +4 -3
  93. {ultralytics-8.2.81.dist-info → ultralytics-8.2.83.dist-info}/RECORD +97 -97
  94. {ultralytics-8.2.81.dist-info → ultralytics-8.2.83.dist-info}/WHEEL +1 -1
  95. {ultralytics-8.2.81.dist-info → ultralytics-8.2.83.dist-info}/LICENSE +0 -0
  96. {ultralytics-8.2.81.dist-info → ultralytics-8.2.83.dist-info}/entry_points.txt +0 -0
  97. {ultralytics-8.2.81.dist-info → ultralytics-8.2.83.dist-info}/top_level.txt +0 -0
tests/test_solutions.py CHANGED
@@ -13,7 +13,6 @@ WORKOUTS_SOLUTION_DEMO = "https://github.com/ultralytics/assets/releases/downloa
13
13
  @pytest.mark.slow
14
14
  def test_major_solutions():
15
15
  """Test the object counting, heatmap, speed estimation and queue management solution."""
16
-
17
16
  safe_download(url=MAJOR_SOLUTIONS_DEMO)
18
17
  model = YOLO("yolov8n.pt")
19
18
  names = model.names
@@ -41,7 +40,6 @@ def test_major_solutions():
41
40
  @pytest.mark.slow
42
41
  def test_aigym():
43
42
  """Test the workouts monitoring solution."""
44
-
45
43
  safe_download(url=WORKOUTS_SOLUTION_DEMO)
46
44
  model = YOLO("yolov8n-pose.pt")
47
45
  cap = cv2.VideoCapture("solution_ci_pose_demo.mp4")
@@ -60,7 +58,6 @@ def test_aigym():
60
58
  @pytest.mark.slow
61
59
  def test_instance_segmentation():
62
60
  """Test the instance segmentation solution."""
63
-
64
61
  from ultralytics.utils.plotting import Annotator, colors
65
62
 
66
63
  model = YOLO("yolov8n-seg.pt")
@@ -86,5 +83,4 @@ def test_instance_segmentation():
86
83
  @pytest.mark.slow
87
84
  def test_streamlit_predict():
88
85
  """Test streamlit predict live inference solution."""
89
-
90
86
  solutions.inference()
ultralytics/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # Ultralytics YOLO 🚀, AGPL-3.0 license
2
2
 
3
- __version__ = "8.2.81"
3
+ __version__ = "8.2.83"
4
4
 
5
5
  import os
6
6
 
@@ -13,6 +13,7 @@ from ultralytics.utils import (
13
13
  DEFAULT_CFG,
14
14
  DEFAULT_CFG_DICT,
15
15
  DEFAULT_CFG_PATH,
16
+ IS_VSCODE,
16
17
  LOGGER,
17
18
  RANK,
18
19
  ROOT,
@@ -25,6 +26,7 @@ from ultralytics.utils import (
25
26
  checks,
26
27
  colorstr,
27
28
  deprecation_warn,
29
+ vscode_msg,
28
30
  yaml_load,
29
31
  yaml_print,
30
32
  )
@@ -198,15 +200,15 @@ def cfg2dict(cfg):
198
200
 
199
201
  Examples:
200
202
  Convert a YAML file path to a dictionary:
201
- >>> config_dict = cfg2dict('config.yaml')
203
+ >>> config_dict = cfg2dict("config.yaml")
202
204
 
203
205
  Convert a SimpleNamespace to a dictionary:
204
206
  >>> from types import SimpleNamespace
205
- >>> config_sn = SimpleNamespace(param1='value1', param2='value2')
207
+ >>> config_sn = SimpleNamespace(param1="value1", param2="value2")
206
208
  >>> config_dict = cfg2dict(config_sn)
207
209
 
208
210
  Pass through an already existing dictionary:
209
- >>> config_dict = cfg2dict({'param1': 'value1', 'param2': 'value2'})
211
+ >>> config_dict = cfg2dict({"param1": "value1", "param2": "value2"})
210
212
 
211
213
  Notes:
212
214
  - If cfg is a path or string, it's loaded as YAML and converted to a dictionary.
@@ -235,7 +237,7 @@ def get_cfg(cfg: Union[str, Path, Dict, SimpleNamespace] = DEFAULT_CFG_DICT, ove
235
237
  Examples:
236
238
  >>> from ultralytics.cfg import get_cfg
237
239
  >>> config = get_cfg() # Load default configuration
238
- >>> config = get_cfg('path/to/config.yaml', overrides={'epochs': 50, 'batch_size': 16})
240
+ >>> config = get_cfg("path/to/config.yaml", overrides={"epochs": 50, "batch_size": 16})
239
241
 
240
242
  Notes:
241
243
  - If both `cfg` and `overrides` are provided, the values in `overrides` will take precedence.
@@ -282,10 +284,10 @@ def check_cfg(cfg, hard=True):
282
284
 
283
285
  Examples:
284
286
  >>> config = {
285
- ... 'epochs': 50, # valid integer
286
- ... 'lr0': 0.01, # valid float
287
- ... 'momentum': 1.2, # invalid float (out of 0.0-1.0 range)
288
- ... 'save': 'true', # invalid bool
287
+ ... "epochs": 50, # valid integer
288
+ ... "lr0": 0.01, # valid float
289
+ ... "momentum": 1.2, # invalid float (out of 0.0-1.0 range)
290
+ ... "save": "true", # invalid bool
289
291
  ... }
290
292
  >>> check_cfg(config, hard=False)
291
293
  >>> print(config)
@@ -345,12 +347,11 @@ def get_save_dir(args, name=None):
345
347
 
346
348
  Examples:
347
349
  >>> from types import SimpleNamespace
348
- >>> args = SimpleNamespace(project='my_project', task='detect', mode='train', exist_ok=True)
350
+ >>> args = SimpleNamespace(project="my_project", task="detect", mode="train", exist_ok=True)
349
351
  >>> save_dir = get_save_dir(args)
350
352
  >>> print(save_dir)
351
353
  my_project/detect/train
352
354
  """
353
-
354
355
  if getattr(args, "save_dir", None):
355
356
  save_dir = args.save_dir
356
357
  else:
@@ -381,7 +382,6 @@ def _handle_deprecation(custom):
381
382
  equivalents. It also handles value conversions where necessary, such as inverting boolean values for
382
383
  'hide_labels' and 'hide_conf'.
383
384
  """
384
-
385
385
  for key in custom.copy().keys():
386
386
  if key == "boxes":
387
387
  deprecation_warn(key, "show_boxes")
@@ -413,8 +413,8 @@ def check_dict_alignment(base: Dict, custom: Dict, e=None):
413
413
  SystemExit: If mismatched keys are found between the custom and base dictionaries.
414
414
 
415
415
  Examples:
416
- >>> base_cfg = {'epochs': 50, 'lr0': 0.01, 'batch_size': 16}
417
- >>> custom_cfg = {'epoch': 100, 'lr': 0.02, 'batch_size': 32}
416
+ >>> base_cfg = {"epochs": 50, "lr0": 0.01, "batch_size": 16}
417
+ >>> custom_cfg = {"epoch": 100, "lr": 0.02, "batch_size": 32}
418
418
  >>> try:
419
419
  ... check_dict_alignment(base_cfg, custom_cfg)
420
420
  ... except SystemExit:
@@ -548,9 +548,9 @@ def handle_yolo_settings(args: List[str]) -> None:
548
548
 
549
549
  def handle_explorer(args: List[str]):
550
550
  """
551
- This function launches a graphical user interface that provides tools for interacting with and analyzing datasets
552
- using the Ultralytics Explorer API. It checks for the required 'streamlit' package and informs the user that the
553
- Explorer dashboard is loading.
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
554
 
555
555
  Args:
556
556
  args (List[str]): A list of optional command line arguments.
@@ -793,11 +793,7 @@ def entrypoint(debug=""):
793
793
  from ultralytics import FastSAM
794
794
 
795
795
  model = FastSAM(model)
796
- elif "sam2" in stem:
797
- from ultralytics import SAM2
798
-
799
- model = SAM2(model)
800
- elif "sam" in stem:
796
+ elif "sam_" in stem or "sam2_" in stem:
801
797
  from ultralytics import SAM
802
798
 
803
799
  model = SAM(model)
@@ -836,6 +832,10 @@ def entrypoint(debug=""):
836
832
  # Show help
837
833
  LOGGER.info(f"💡 Learn more at https://docs.ultralytics.com/modes/{mode}")
838
834
 
835
+ # Recommend VS Code extension
836
+ if IS_VSCODE and SETTINGS.get("vscode_msg", True):
837
+ LOGGER.info(vscode_msg())
838
+
839
839
 
840
840
  # Special modes --------------------------------------------------------------------------------------------------------
841
841
  def copy_default_cfg():
@@ -21,7 +21,7 @@ def auto_annotate(data, det_model="yolov8x.pt", sam_model="sam_b.pt", device="",
21
21
 
22
22
  Examples:
23
23
  >>> from ultralytics.data.annotator import auto_annotate
24
- >>> auto_annotate(data='ultralytics/assets', det_model='yolov8n.pt', sam_model='mobile_sam.pt')
24
+ >>> auto_annotate(data="ultralytics/assets", det_model="yolov8n.pt", sam_model="mobile_sam.pt")
25
25
 
26
26
  Notes:
27
27
  - The function creates a new directory for output if not specified.
@@ -38,7 +38,7 @@ class BaseTransform:
38
38
 
39
39
  Examples:
40
40
  >>> transform = BaseTransform()
41
- >>> labels = {'image': np.array(...), 'instances': [...], 'semantic': np.array(...)}
41
+ >>> labels = {"image": np.array(...), "instances": [...], "semantic": np.array(...)}
42
42
  >>> transformed_labels = transform(labels)
43
43
  """
44
44
 
@@ -93,7 +93,7 @@ class BaseTransform:
93
93
 
94
94
  Examples:
95
95
  >>> transform = BaseTransform()
96
- >>> labels = {'instances': Instances(xyxy=torch.rand(5, 4), cls=torch.randint(0, 80, (5,)))}
96
+ >>> labels = {"instances": Instances(xyxy=torch.rand(5, 4), cls=torch.randint(0, 80, (5,)))}
97
97
  >>> transformed_labels = transform.apply_instances(labels)
98
98
  """
99
99
  pass
@@ -135,7 +135,7 @@ class BaseTransform:
135
135
 
136
136
  Examples:
137
137
  >>> transform = BaseTransform()
138
- >>> labels = {'img': np.random.rand(640, 640, 3), 'instances': []}
138
+ >>> labels = {"img": np.random.rand(640, 640, 3), "instances": []}
139
139
  >>> transformed_labels = transform(labels)
140
140
  """
141
141
  self.apply_image(labels)
@@ -338,6 +338,7 @@ class BaseMixTransform:
338
338
  ... def _mix_transform(self, labels):
339
339
  ... # Implement custom mix logic here
340
340
  ... return labels
341
+ ...
341
342
  ... def get_indexes(self):
342
343
  ... return [random.randint(0, len(self.dataset) - 1) for _ in range(3)]
343
344
  >>> dataset = YourDataset()
@@ -421,7 +422,7 @@ class BaseMixTransform:
421
422
 
422
423
  Examples:
423
424
  >>> transform = BaseMixTransform(dataset)
424
- >>> labels = {'image': img, 'bboxes': boxes, 'mix_labels': [{'image': img2, 'bboxes': boxes2}]}
425
+ >>> labels = {"image": img, "bboxes": boxes, "mix_labels": [{"image": img2, "bboxes": boxes2}]}
425
426
  >>> augmented_labels = transform._mix_transform(labels)
426
427
  """
427
428
  raise NotImplementedError
@@ -456,20 +457,17 @@ class BaseMixTransform:
456
457
 
457
458
  Examples:
458
459
  >>> labels = {
459
- ... 'texts': [['cat'], ['dog']],
460
- ... 'cls': torch.tensor([[0], [1]]),
461
- ... 'mix_labels': [{
462
- ... 'texts': [['bird'], ['fish']],
463
- ... 'cls': torch.tensor([[0], [1]])
464
- ... }]
460
+ ... "texts": [["cat"], ["dog"]],
461
+ ... "cls": torch.tensor([[0], [1]]),
462
+ ... "mix_labels": [{"texts": [["bird"], ["fish"]], "cls": torch.tensor([[0], [1]])}],
465
463
  ... }
466
464
  >>> updated_labels = self._update_label_text(labels)
467
- >>> print(updated_labels['texts'])
465
+ >>> print(updated_labels["texts"])
468
466
  [['cat'], ['dog'], ['bird'], ['fish']]
469
- >>> print(updated_labels['cls'])
467
+ >>> print(updated_labels["cls"])
470
468
  tensor([[0],
471
469
  [1]])
472
- >>> print(updated_labels['mix_labels'][0]['cls'])
470
+ >>> print(updated_labels["mix_labels"][0]["cls"])
473
471
  tensor([[2],
474
472
  [3]])
475
473
  """
@@ -616,9 +614,12 @@ class Mosaic(BaseMixTransform):
616
614
 
617
615
  Examples:
618
616
  >>> mosaic = Mosaic(dataset, imgsz=640, p=1.0, n=3)
619
- >>> labels = {'img': np.random.rand(480, 640, 3), 'mix_labels': [{'img': np.random.rand(480, 640, 3)} for _ in range(2)]}
617
+ >>> labels = {
618
+ ... "img": np.random.rand(480, 640, 3),
619
+ ... "mix_labels": [{"img": np.random.rand(480, 640, 3)} for _ in range(2)],
620
+ ... }
620
621
  >>> result = mosaic._mosaic3(labels)
621
- >>> print(result['img'].shape)
622
+ >>> print(result["img"].shape)
622
623
  (640, 640, 3)
623
624
  """
624
625
  mosaic_labels = []
@@ -670,9 +671,10 @@ class Mosaic(BaseMixTransform):
670
671
 
671
672
  Examples:
672
673
  >>> mosaic = Mosaic(dataset, imgsz=640, p=1.0, n=4)
673
- >>> labels = {"img": np.random.rand(480, 640, 3), "mix_labels": [
674
- ... {"img": np.random.rand(480, 640, 3)} for _ in range(3)
675
- ... ]}
674
+ >>> labels = {
675
+ ... "img": np.random.rand(480, 640, 3),
676
+ ... "mix_labels": [{"img": np.random.rand(480, 640, 3)} for _ in range(3)],
677
+ ... }
676
678
  >>> result = mosaic._mosaic4(labels)
677
679
  >>> assert result["img"].shape == (1280, 1280, 3)
678
680
  """
@@ -734,7 +736,7 @@ class Mosaic(BaseMixTransform):
734
736
  >>> mosaic = Mosaic(dataset, imgsz=640, p=1.0, n=9)
735
737
  >>> input_labels = dataset[0]
736
738
  >>> mosaic_result = mosaic._mosaic9(input_labels)
737
- >>> mosaic_image = mosaic_result['img']
739
+ >>> mosaic_image = mosaic_result["img"]
738
740
  """
739
741
  mosaic_labels = []
740
742
  s = self.imgsz
@@ -898,7 +900,7 @@ class MixUp(BaseMixTransform):
898
900
 
899
901
  Examples:
900
902
  >>> from ultralytics.data.dataset import YOLODataset
901
- >>> dataset = YOLODataset('path/to/data.yaml')
903
+ >>> dataset = YOLODataset("path/to/data.yaml")
902
904
  >>> mixup = MixUp(dataset, pre_transform=None, p=0.5)
903
905
  """
904
906
  super().__init__(dataset=dataset, pre_transform=pre_transform, p=p)
@@ -974,10 +976,10 @@ class RandomPerspective:
974
976
  Examples:
975
977
  >>> transform = RandomPerspective(degrees=10, translate=0.1, scale=0.1, shear=10)
976
978
  >>> image = np.random.randint(0, 255, (640, 640, 3), dtype=np.uint8)
977
- >>> labels = {'img': image, 'cls': np.array([0, 1]), 'instances': Instances(...)}
979
+ >>> labels = {"img": image, "cls": np.array([0, 1]), "instances": Instances(...)}
978
980
  >>> result = transform(labels)
979
- >>> transformed_image = result['img']
980
- >>> transformed_instances = result['instances']
981
+ >>> transformed_image = result["img"]
982
+ >>> transformed_instances = result["instances"]
981
983
  """
982
984
 
983
985
  def __init__(
@@ -1003,7 +1005,6 @@ class RandomPerspective:
1003
1005
  >>> transform = RandomPerspective(degrees=10.0, translate=0.1, scale=0.5, shear=5.0)
1004
1006
  >>> result = transform(labels) # Apply random perspective to labels
1005
1007
  """
1006
-
1007
1008
  self.degrees = degrees
1008
1009
  self.translate = translate
1009
1010
  self.scale = scale
@@ -1036,7 +1037,6 @@ class RandomPerspective:
1036
1037
  >>> border = (10, 10)
1037
1038
  >>> transformed_img, matrix, scale = affine_transform(img, border)
1038
1039
  """
1039
-
1040
1040
  # Center
1041
1041
  C = np.eye(3, dtype=np.float32)
1042
1042
 
@@ -1209,12 +1209,12 @@ class RandomPerspective:
1209
1209
  >>> transform = RandomPerspective()
1210
1210
  >>> image = np.random.randint(0, 255, (640, 640, 3), dtype=np.uint8)
1211
1211
  >>> labels = {
1212
- ... 'img': image,
1213
- ... 'cls': np.array([0, 1, 2]),
1214
- ... 'instances': Instances(bboxes=np.array([[10, 10, 50, 50], [100, 100, 150, 150]]))
1212
+ ... "img": image,
1213
+ ... "cls": np.array([0, 1, 2]),
1214
+ ... "instances": Instances(bboxes=np.array([[10, 10, 50, 50], [100, 100, 150, 150]])),
1215
1215
  ... }
1216
1216
  >>> result = transform(labels)
1217
- >>> assert result['img'].shape[:2] == result['resized_shape']
1217
+ >>> assert result["img"].shape[:2] == result["resized_shape"]
1218
1218
  """
1219
1219
  if self.pre_transform and "mosaic_border" not in labels:
1220
1220
  labels = self.pre_transform(labels)
@@ -1358,9 +1358,9 @@ class RandomHSV:
1358
1358
 
1359
1359
  Examples:
1360
1360
  >>> hsv_augmenter = RandomHSV(hgain=0.5, sgain=0.5, vgain=0.5)
1361
- >>> labels = {'img': np.random.randint(0, 255, (100, 100, 3), dtype=np.uint8)}
1361
+ >>> labels = {"img": np.random.randint(0, 255, (100, 100, 3), dtype=np.uint8)}
1362
1362
  >>> hsv_augmenter(labels)
1363
- >>> augmented_img = labels['img']
1363
+ >>> augmented_img = labels["img"]
1364
1364
  """
1365
1365
  img = labels["img"]
1366
1366
  if self.hgain or self.sgain or self.vgain:
@@ -1394,7 +1394,7 @@ class RandomFlip:
1394
1394
  __call__: Applies the random flip transformation to an image and its annotations.
1395
1395
 
1396
1396
  Examples:
1397
- >>> transform = RandomFlip(p=0.5, direction='horizontal')
1397
+ >>> transform = RandomFlip(p=0.5, direction="horizontal")
1398
1398
  >>> result = transform({"img": image, "instances": instances})
1399
1399
  >>> flipped_image = result["img"]
1400
1400
  >>> flipped_instances = result["instances"]
@@ -1416,8 +1416,8 @@ class RandomFlip:
1416
1416
  AssertionError: If direction is not 'horizontal' or 'vertical', or if p is not between 0 and 1.
1417
1417
 
1418
1418
  Examples:
1419
- >>> flip = RandomFlip(p=0.5, direction='horizontal')
1420
- >>> flip = RandomFlip(p=0.7, direction='vertical', flip_idx=[1, 0, 3, 2, 5, 4])
1419
+ >>> flip = RandomFlip(p=0.5, direction="horizontal")
1420
+ >>> flip = RandomFlip(p=0.7, direction="vertical", flip_idx=[1, 0, 3, 2, 5, 4])
1421
1421
  """
1422
1422
  assert direction in {"horizontal", "vertical"}, f"Support direction `horizontal` or `vertical`, got {direction}"
1423
1423
  assert 0 <= p <= 1.0, f"The probability should be in range [0, 1], but got {p}."
@@ -1446,8 +1446,8 @@ class RandomFlip:
1446
1446
  'instances' (ultralytics.utils.instance.Instances): Updated instances matching the flipped image.
1447
1447
 
1448
1448
  Examples:
1449
- >>> labels = {'img': np.random.rand(640, 640, 3), 'instances': Instances(...)}
1450
- >>> random_flip = RandomFlip(p=0.5, direction='horizontal')
1449
+ >>> labels = {"img": np.random.rand(640, 640, 3), "instances": Instances(...)}
1450
+ >>> random_flip = RandomFlip(p=0.5, direction="horizontal")
1451
1451
  >>> flipped_labels = random_flip(labels)
1452
1452
  """
1453
1453
  img = labels["img"]
@@ -1493,8 +1493,8 @@ class LetterBox:
1493
1493
  Examples:
1494
1494
  >>> transform = LetterBox(new_shape=(640, 640))
1495
1495
  >>> result = transform(labels)
1496
- >>> resized_img = result['img']
1497
- >>> updated_instances = result['instances']
1496
+ >>> resized_img = result["img"]
1497
+ >>> updated_instances = result["instances"]
1498
1498
  """
1499
1499
 
1500
1500
  def __init__(self, new_shape=(640, 640), auto=False, scaleFill=False, scaleup=True, center=True, stride=32):
@@ -1548,9 +1548,9 @@ class LetterBox:
1548
1548
 
1549
1549
  Examples:
1550
1550
  >>> letterbox = LetterBox(new_shape=(640, 640))
1551
- >>> result = letterbox(labels={'img': np.zeros((480, 640, 3)), 'instances': Instances(...)})
1552
- >>> resized_img = result['img']
1553
- >>> updated_instances = result['instances']
1551
+ >>> result = letterbox(labels={"img": np.zeros((480, 640, 3)), "instances": Instances(...)})
1552
+ >>> resized_img = result["img"]
1553
+ >>> updated_instances = result["instances"]
1554
1554
  """
1555
1555
  if labels is None:
1556
1556
  labels = {}
@@ -1616,7 +1616,7 @@ class LetterBox:
1616
1616
 
1617
1617
  Examples:
1618
1618
  >>> letterbox = LetterBox(new_shape=(640, 640))
1619
- >>> labels = {'instances': Instances(...)}
1619
+ >>> labels = {"instances": Instances(...)}
1620
1620
  >>> ratio = (0.5, 0.5)
1621
1621
  >>> padw, padh = 10, 20
1622
1622
  >>> updated_labels = letterbox._update_labels(labels, ratio, padw, padh)
@@ -1643,7 +1643,7 @@ class CopyPaste:
1643
1643
  Examples:
1644
1644
  >>> copypaste = CopyPaste(p=0.5)
1645
1645
  >>> augmented_labels = copypaste(labels)
1646
- >>> augmented_image = augmented_labels['img']
1646
+ >>> augmented_image = augmented_labels["img"]
1647
1647
  """
1648
1648
 
1649
1649
  def __init__(self, p=0.5) -> None:
@@ -1680,7 +1680,7 @@ class CopyPaste:
1680
1680
  (Dict): Dictionary with augmented image and updated instances under 'img', 'cls', and 'instances' keys.
1681
1681
 
1682
1682
  Examples:
1683
- >>> labels = {'img': np.random.rand(640, 640, 3), 'cls': np.array([0, 1, 2]), 'instances': Instances(...)}
1683
+ >>> labels = {"img": np.random.rand(640, 640, 3), "cls": np.array([0, 1, 2]), "instances": Instances(...)}
1684
1684
  >>> augmenter = CopyPaste(p=0.5)
1685
1685
  >>> augmented_labels = augmenter(labels)
1686
1686
  """
@@ -1765,8 +1765,8 @@ class Albumentations:
1765
1765
  Examples:
1766
1766
  >>> transform = Albumentations(p=0.5)
1767
1767
  >>> augmented = transform(image=image, bboxes=bboxes, class_labels=classes)
1768
- >>> augmented_image = augmented['image']
1769
- >>> augmented_bboxes = augmented['bboxes']
1768
+ >>> augmented_image = augmented["image"]
1769
+ >>> augmented_bboxes = augmented["bboxes"]
1770
1770
 
1771
1771
  Notes:
1772
1772
  - Requires Albumentations version 1.0.3 or higher.
@@ -1871,7 +1871,7 @@ class Albumentations:
1871
1871
  >>> labels = {
1872
1872
  ... "img": np.random.rand(640, 640, 3),
1873
1873
  ... "cls": np.array([0, 1]),
1874
- ... "instances": Instances(bboxes=np.array([[0, 0, 1, 1], [0.5, 0.5, 0.8, 0.8]]))
1874
+ ... "instances": Instances(bboxes=np.array([[0, 0, 1, 1], [0.5, 0.5, 0.8, 0.8]])),
1875
1875
  ... }
1876
1876
  >>> augmented = transform(labels)
1877
1877
  >>> assert augmented["img"].shape == (640, 640, 3)
@@ -1927,11 +1927,11 @@ class Format:
1927
1927
  _format_segments: Converts polygon points to bitmap masks.
1928
1928
 
1929
1929
  Examples:
1930
- >>> formatter = Format(bbox_format='xywh', normalize=True, return_mask=True)
1930
+ >>> formatter = Format(bbox_format="xywh", normalize=True, return_mask=True)
1931
1931
  >>> formatted_labels = formatter(labels)
1932
- >>> img = formatted_labels['img']
1933
- >>> bboxes = formatted_labels['bboxes']
1934
- >>> masks = formatted_labels['masks']
1932
+ >>> img = formatted_labels["img"]
1933
+ >>> bboxes = formatted_labels["bboxes"]
1934
+ >>> masks = formatted_labels["masks"]
1935
1935
  """
1936
1936
 
1937
1937
  def __init__(
@@ -1975,7 +1975,7 @@ class Format:
1975
1975
  bgr (float): The probability to return BGR images.
1976
1976
 
1977
1977
  Examples:
1978
- >>> format = Format(bbox_format='xyxy', return_mask=True, return_keypoint=False)
1978
+ >>> format = Format(bbox_format="xyxy", return_mask=True, return_keypoint=False)
1979
1979
  >>> print(format.bbox_format)
1980
1980
  xyxy
1981
1981
  """
@@ -2013,8 +2013,8 @@ class Format:
2013
2013
  - 'batch_idx': Batch index tensor (if batch_idx is True).
2014
2014
 
2015
2015
  Examples:
2016
- >>> formatter = Format(bbox_format='xywh', normalize=True, return_mask=True)
2017
- >>> labels = {'img': np.random.rand(640, 640, 3), 'cls': np.array([0, 1]), 'instances': Instances(...)}
2016
+ >>> formatter = Format(bbox_format="xywh", normalize=True, return_mask=True)
2017
+ >>> labels = {"img": np.random.rand(640, 640, 3), "cls": np.array([0, 1]), "instances": Instances(...)}
2018
2018
  >>> formatted_labels = formatter(labels)
2019
2019
  >>> print(formatted_labels.keys())
2020
2020
  """
@@ -2275,8 +2275,8 @@ def v8_transforms(dataset, imgsz, hyp, stretch=False):
2275
2275
 
2276
2276
  Examples:
2277
2277
  >>> from ultralytics.data.dataset import YOLODataset
2278
- >>> dataset = YOLODataset(img_path='path/to/images', imgsz=640)
2279
- >>> hyp = {'mosaic': 1.0, 'copy_paste': 0.5, 'degrees': 10.0, 'translate': 0.2, 'scale': 0.9}
2278
+ >>> dataset = YOLODataset(img_path="path/to/images", imgsz=640)
2279
+ >>> hyp = {"mosaic": 1.0, "copy_paste": 0.5, "degrees": 10.0, "translate": 0.2, "scale": 0.9}
2280
2280
  >>> transforms = v8_transforms(dataset, imgsz=640, hyp=hyp)
2281
2281
  >>> augmented_data = transforms(dataset[0])
2282
2282
  """
@@ -2343,7 +2343,7 @@ def classify_transforms(
2343
2343
 
2344
2344
  Examples:
2345
2345
  >>> transforms = classify_transforms(size=224)
2346
- >>> img = Image.open('path/to/image.jpg')
2346
+ >>> img = Image.open("path/to/image.jpg")
2347
2347
  >>> transformed_img = transforms(img)
2348
2348
  """
2349
2349
  import torchvision.transforms as T # scope for faster 'import ultralytics'
@@ -2415,7 +2415,7 @@ def classify_augmentations(
2415
2415
  (torchvision.transforms.Compose): A composition of image augmentation transforms.
2416
2416
 
2417
2417
  Examples:
2418
- >>> transforms = classify_augmentations(size=224, auto_augment='randaugment')
2418
+ >>> transforms = classify_augmentations(size=224, auto_augment="randaugment")
2419
2419
  >>> augmented_image = transforms(original_image)
2420
2420
  """
2421
2421
  # Transforms to apply if Albumentations not installed
ultralytics/data/base.py CHANGED
@@ -298,10 +298,10 @@ class BaseDataset(Dataset):
298
298
  im_file=im_file,
299
299
  shape=shape, # format: (height, width)
300
300
  cls=cls,
301
- bboxes=bboxes, # xywh
301
+ bboxes=bboxes, # xywh
302
302
  segments=segments, # xy
303
- keypoints=keypoints, # xy
304
- normalized=True, # or False
303
+ keypoints=keypoints, # xy
304
+ normalized=True, # or False
305
305
  bbox_format="xyxy", # or xywh, ltwh
306
306
  )
307
307
  ```
@@ -115,7 +115,7 @@ def coco91_to_coco80_class():
115
115
 
116
116
 
117
117
  def coco80_to_coco91_class():
118
- """
118
+ r"""
119
119
  Converts 80-index (val2014) to 91-index (paper).
120
120
  For details see https://tech.amikelive.com/node-718/what-object-categories-labels-are-in-coco-dataset/.
121
121
 
@@ -123,8 +123,8 @@ def coco80_to_coco91_class():
123
123
  ```python
124
124
  import numpy as np
125
125
 
126
- a = np.loadtxt('data/coco.names', dtype='str', delimiter='\n')
127
- b = np.loadtxt('data/coco_paper.names', dtype='str', delimiter='\n')
126
+ a = np.loadtxt("data/coco.names", dtype="str", delimiter="\n")
127
+ b = np.loadtxt("data/coco_paper.names", dtype="str", delimiter="\n")
128
128
  x1 = [list(a[i] == b).index(True) + 1 for i in range(80)] # darknet to coco
129
129
  x2 = [list(b[i] == a).index(True) if any(b[i] == a) else None for i in range(91)] # coco to darknet
130
130
  ```
@@ -236,14 +236,13 @@ def convert_coco(
236
236
  ```python
237
237
  from ultralytics.data.converter import convert_coco
238
238
 
239
- convert_coco('../datasets/coco/annotations/', use_segments=True, use_keypoints=False, cls91to80=True)
240
- convert_coco('../datasets/lvis/annotations/', use_segments=True, use_keypoints=False, cls91to80=False, lvis=True)
239
+ convert_coco("../datasets/coco/annotations/", use_segments=True, use_keypoints=False, cls91to80=True)
240
+ convert_coco("../datasets/lvis/annotations/", use_segments=True, use_keypoints=False, cls91to80=False, lvis=True)
241
241
  ```
242
242
 
243
243
  Output:
244
244
  Generates output files in the specified output directory.
245
245
  """
246
-
247
246
  # Create dataset directory
248
247
  save_dir = increment_path(save_dir) # increment if save directory already exists
249
248
  for p in save_dir / "labels", save_dir / "images":
@@ -351,7 +350,7 @@ def convert_segment_masks_to_yolo_seg(masks_dir, output_dir, classes):
351
350
  from ultralytics.data.converter import convert_segment_masks_to_yolo_seg
352
351
 
353
352
  # The classes here is the total classes in the dataset, for COCO dataset we have 80 classes
354
- convert_segment_masks_to_yolo_seg('path/to/masks_directory', 'path/to/output/directory', classes=80)
353
+ convert_segment_masks_to_yolo_seg("path/to/masks_directory", "path/to/output/directory", classes=80)
355
354
  ```
356
355
 
357
356
  Notes:
@@ -429,7 +428,7 @@ def convert_dota_to_yolo_obb(dota_root_path: str):
429
428
  ```python
430
429
  from ultralytics.data.converter import convert_dota_to_yolo_obb
431
430
 
432
- convert_dota_to_yolo_obb('path/to/DOTA')
431
+ convert_dota_to_yolo_obb("path/to/DOTA")
433
432
  ```
434
433
 
435
434
  Notes: