dgenerate-ultralytics-headless 8.3.253__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 (299) hide show
  1. dgenerate_ultralytics_headless-8.3.253.dist-info/METADATA +405 -0
  2. dgenerate_ultralytics_headless-8.3.253.dist-info/RECORD +299 -0
  3. dgenerate_ultralytics_headless-8.3.253.dist-info/WHEEL +5 -0
  4. dgenerate_ultralytics_headless-8.3.253.dist-info/entry_points.txt +3 -0
  5. dgenerate_ultralytics_headless-8.3.253.dist-info/licenses/LICENSE +661 -0
  6. dgenerate_ultralytics_headless-8.3.253.dist-info/top_level.txt +1 -0
  7. tests/__init__.py +23 -0
  8. tests/conftest.py +59 -0
  9. tests/test_cli.py +131 -0
  10. tests/test_cuda.py +216 -0
  11. tests/test_engine.py +157 -0
  12. tests/test_exports.py +309 -0
  13. tests/test_integrations.py +151 -0
  14. tests/test_python.py +777 -0
  15. tests/test_solutions.py +371 -0
  16. ultralytics/__init__.py +48 -0
  17. ultralytics/assets/bus.jpg +0 -0
  18. ultralytics/assets/zidane.jpg +0 -0
  19. ultralytics/cfg/__init__.py +1028 -0
  20. ultralytics/cfg/datasets/Argoverse.yaml +78 -0
  21. ultralytics/cfg/datasets/DOTAv1.5.yaml +37 -0
  22. ultralytics/cfg/datasets/DOTAv1.yaml +36 -0
  23. ultralytics/cfg/datasets/GlobalWheat2020.yaml +68 -0
  24. ultralytics/cfg/datasets/HomeObjects-3K.yaml +32 -0
  25. ultralytics/cfg/datasets/ImageNet.yaml +2025 -0
  26. ultralytics/cfg/datasets/Objects365.yaml +447 -0
  27. ultralytics/cfg/datasets/SKU-110K.yaml +58 -0
  28. ultralytics/cfg/datasets/TT100K.yaml +346 -0
  29. ultralytics/cfg/datasets/VOC.yaml +102 -0
  30. ultralytics/cfg/datasets/VisDrone.yaml +87 -0
  31. ultralytics/cfg/datasets/african-wildlife.yaml +25 -0
  32. ultralytics/cfg/datasets/brain-tumor.yaml +22 -0
  33. ultralytics/cfg/datasets/carparts-seg.yaml +44 -0
  34. ultralytics/cfg/datasets/coco-pose.yaml +64 -0
  35. ultralytics/cfg/datasets/coco.yaml +118 -0
  36. ultralytics/cfg/datasets/coco128-seg.yaml +101 -0
  37. ultralytics/cfg/datasets/coco128.yaml +101 -0
  38. ultralytics/cfg/datasets/coco8-grayscale.yaml +103 -0
  39. ultralytics/cfg/datasets/coco8-multispectral.yaml +104 -0
  40. ultralytics/cfg/datasets/coco8-pose.yaml +47 -0
  41. ultralytics/cfg/datasets/coco8-seg.yaml +101 -0
  42. ultralytics/cfg/datasets/coco8.yaml +101 -0
  43. ultralytics/cfg/datasets/construction-ppe.yaml +32 -0
  44. ultralytics/cfg/datasets/crack-seg.yaml +22 -0
  45. ultralytics/cfg/datasets/dog-pose.yaml +52 -0
  46. ultralytics/cfg/datasets/dota8-multispectral.yaml +38 -0
  47. ultralytics/cfg/datasets/dota8.yaml +35 -0
  48. ultralytics/cfg/datasets/hand-keypoints.yaml +50 -0
  49. ultralytics/cfg/datasets/kitti.yaml +27 -0
  50. ultralytics/cfg/datasets/lvis.yaml +1240 -0
  51. ultralytics/cfg/datasets/medical-pills.yaml +21 -0
  52. ultralytics/cfg/datasets/open-images-v7.yaml +663 -0
  53. ultralytics/cfg/datasets/package-seg.yaml +22 -0
  54. ultralytics/cfg/datasets/signature.yaml +21 -0
  55. ultralytics/cfg/datasets/tiger-pose.yaml +41 -0
  56. ultralytics/cfg/datasets/xView.yaml +155 -0
  57. ultralytics/cfg/default.yaml +130 -0
  58. ultralytics/cfg/models/11/yolo11-cls-resnet18.yaml +17 -0
  59. ultralytics/cfg/models/11/yolo11-cls.yaml +33 -0
  60. ultralytics/cfg/models/11/yolo11-obb.yaml +50 -0
  61. ultralytics/cfg/models/11/yolo11-pose.yaml +51 -0
  62. ultralytics/cfg/models/11/yolo11-seg.yaml +50 -0
  63. ultralytics/cfg/models/11/yolo11.yaml +50 -0
  64. ultralytics/cfg/models/11/yoloe-11-seg.yaml +48 -0
  65. ultralytics/cfg/models/11/yoloe-11.yaml +48 -0
  66. ultralytics/cfg/models/12/yolo12-cls.yaml +32 -0
  67. ultralytics/cfg/models/12/yolo12-obb.yaml +48 -0
  68. ultralytics/cfg/models/12/yolo12-pose.yaml +49 -0
  69. ultralytics/cfg/models/12/yolo12-seg.yaml +48 -0
  70. ultralytics/cfg/models/12/yolo12.yaml +48 -0
  71. ultralytics/cfg/models/rt-detr/rtdetr-l.yaml +53 -0
  72. ultralytics/cfg/models/rt-detr/rtdetr-resnet101.yaml +45 -0
  73. ultralytics/cfg/models/rt-detr/rtdetr-resnet50.yaml +45 -0
  74. ultralytics/cfg/models/rt-detr/rtdetr-x.yaml +57 -0
  75. ultralytics/cfg/models/v10/yolov10b.yaml +45 -0
  76. ultralytics/cfg/models/v10/yolov10l.yaml +45 -0
  77. ultralytics/cfg/models/v10/yolov10m.yaml +45 -0
  78. ultralytics/cfg/models/v10/yolov10n.yaml +45 -0
  79. ultralytics/cfg/models/v10/yolov10s.yaml +45 -0
  80. ultralytics/cfg/models/v10/yolov10x.yaml +45 -0
  81. ultralytics/cfg/models/v3/yolov3-spp.yaml +49 -0
  82. ultralytics/cfg/models/v3/yolov3-tiny.yaml +40 -0
  83. ultralytics/cfg/models/v3/yolov3.yaml +49 -0
  84. ultralytics/cfg/models/v5/yolov5-p6.yaml +62 -0
  85. ultralytics/cfg/models/v5/yolov5.yaml +51 -0
  86. ultralytics/cfg/models/v6/yolov6.yaml +56 -0
  87. ultralytics/cfg/models/v8/yoloe-v8-seg.yaml +48 -0
  88. ultralytics/cfg/models/v8/yoloe-v8.yaml +48 -0
  89. ultralytics/cfg/models/v8/yolov8-cls-resnet101.yaml +28 -0
  90. ultralytics/cfg/models/v8/yolov8-cls-resnet50.yaml +28 -0
  91. ultralytics/cfg/models/v8/yolov8-cls.yaml +32 -0
  92. ultralytics/cfg/models/v8/yolov8-ghost-p2.yaml +58 -0
  93. ultralytics/cfg/models/v8/yolov8-ghost-p6.yaml +60 -0
  94. ultralytics/cfg/models/v8/yolov8-ghost.yaml +50 -0
  95. ultralytics/cfg/models/v8/yolov8-obb.yaml +49 -0
  96. ultralytics/cfg/models/v8/yolov8-p2.yaml +57 -0
  97. ultralytics/cfg/models/v8/yolov8-p6.yaml +59 -0
  98. ultralytics/cfg/models/v8/yolov8-pose-p6.yaml +60 -0
  99. ultralytics/cfg/models/v8/yolov8-pose.yaml +50 -0
  100. ultralytics/cfg/models/v8/yolov8-rtdetr.yaml +49 -0
  101. ultralytics/cfg/models/v8/yolov8-seg-p6.yaml +59 -0
  102. ultralytics/cfg/models/v8/yolov8-seg.yaml +49 -0
  103. ultralytics/cfg/models/v8/yolov8-world.yaml +51 -0
  104. ultralytics/cfg/models/v8/yolov8-worldv2.yaml +49 -0
  105. ultralytics/cfg/models/v8/yolov8.yaml +49 -0
  106. ultralytics/cfg/models/v9/yolov9c-seg.yaml +41 -0
  107. ultralytics/cfg/models/v9/yolov9c.yaml +41 -0
  108. ultralytics/cfg/models/v9/yolov9e-seg.yaml +64 -0
  109. ultralytics/cfg/models/v9/yolov9e.yaml +64 -0
  110. ultralytics/cfg/models/v9/yolov9m.yaml +41 -0
  111. ultralytics/cfg/models/v9/yolov9s.yaml +41 -0
  112. ultralytics/cfg/models/v9/yolov9t.yaml +41 -0
  113. ultralytics/cfg/trackers/botsort.yaml +21 -0
  114. ultralytics/cfg/trackers/bytetrack.yaml +12 -0
  115. ultralytics/data/__init__.py +26 -0
  116. ultralytics/data/annotator.py +66 -0
  117. ultralytics/data/augment.py +2801 -0
  118. ultralytics/data/base.py +435 -0
  119. ultralytics/data/build.py +437 -0
  120. ultralytics/data/converter.py +855 -0
  121. ultralytics/data/dataset.py +834 -0
  122. ultralytics/data/loaders.py +704 -0
  123. ultralytics/data/scripts/download_weights.sh +18 -0
  124. ultralytics/data/scripts/get_coco.sh +61 -0
  125. ultralytics/data/scripts/get_coco128.sh +18 -0
  126. ultralytics/data/scripts/get_imagenet.sh +52 -0
  127. ultralytics/data/split.py +138 -0
  128. ultralytics/data/split_dota.py +344 -0
  129. ultralytics/data/utils.py +798 -0
  130. ultralytics/engine/__init__.py +1 -0
  131. ultralytics/engine/exporter.py +1580 -0
  132. ultralytics/engine/model.py +1125 -0
  133. ultralytics/engine/predictor.py +508 -0
  134. ultralytics/engine/results.py +1522 -0
  135. ultralytics/engine/trainer.py +977 -0
  136. ultralytics/engine/tuner.py +449 -0
  137. ultralytics/engine/validator.py +387 -0
  138. ultralytics/hub/__init__.py +166 -0
  139. ultralytics/hub/auth.py +151 -0
  140. ultralytics/hub/google/__init__.py +174 -0
  141. ultralytics/hub/session.py +422 -0
  142. ultralytics/hub/utils.py +162 -0
  143. ultralytics/models/__init__.py +9 -0
  144. ultralytics/models/fastsam/__init__.py +7 -0
  145. ultralytics/models/fastsam/model.py +79 -0
  146. ultralytics/models/fastsam/predict.py +169 -0
  147. ultralytics/models/fastsam/utils.py +23 -0
  148. ultralytics/models/fastsam/val.py +38 -0
  149. ultralytics/models/nas/__init__.py +7 -0
  150. ultralytics/models/nas/model.py +98 -0
  151. ultralytics/models/nas/predict.py +56 -0
  152. ultralytics/models/nas/val.py +38 -0
  153. ultralytics/models/rtdetr/__init__.py +7 -0
  154. ultralytics/models/rtdetr/model.py +63 -0
  155. ultralytics/models/rtdetr/predict.py +88 -0
  156. ultralytics/models/rtdetr/train.py +89 -0
  157. ultralytics/models/rtdetr/val.py +216 -0
  158. ultralytics/models/sam/__init__.py +25 -0
  159. ultralytics/models/sam/amg.py +275 -0
  160. ultralytics/models/sam/build.py +365 -0
  161. ultralytics/models/sam/build_sam3.py +377 -0
  162. ultralytics/models/sam/model.py +169 -0
  163. ultralytics/models/sam/modules/__init__.py +1 -0
  164. ultralytics/models/sam/modules/blocks.py +1067 -0
  165. ultralytics/models/sam/modules/decoders.py +495 -0
  166. ultralytics/models/sam/modules/encoders.py +794 -0
  167. ultralytics/models/sam/modules/memory_attention.py +298 -0
  168. ultralytics/models/sam/modules/sam.py +1160 -0
  169. ultralytics/models/sam/modules/tiny_encoder.py +979 -0
  170. ultralytics/models/sam/modules/transformer.py +344 -0
  171. ultralytics/models/sam/modules/utils.py +512 -0
  172. ultralytics/models/sam/predict.py +3940 -0
  173. ultralytics/models/sam/sam3/__init__.py +3 -0
  174. ultralytics/models/sam/sam3/decoder.py +546 -0
  175. ultralytics/models/sam/sam3/encoder.py +529 -0
  176. ultralytics/models/sam/sam3/geometry_encoders.py +415 -0
  177. ultralytics/models/sam/sam3/maskformer_segmentation.py +286 -0
  178. ultralytics/models/sam/sam3/model_misc.py +199 -0
  179. ultralytics/models/sam/sam3/necks.py +129 -0
  180. ultralytics/models/sam/sam3/sam3_image.py +339 -0
  181. ultralytics/models/sam/sam3/text_encoder_ve.py +307 -0
  182. ultralytics/models/sam/sam3/vitdet.py +547 -0
  183. ultralytics/models/sam/sam3/vl_combiner.py +160 -0
  184. ultralytics/models/utils/__init__.py +1 -0
  185. ultralytics/models/utils/loss.py +466 -0
  186. ultralytics/models/utils/ops.py +315 -0
  187. ultralytics/models/yolo/__init__.py +7 -0
  188. ultralytics/models/yolo/classify/__init__.py +7 -0
  189. ultralytics/models/yolo/classify/predict.py +90 -0
  190. ultralytics/models/yolo/classify/train.py +202 -0
  191. ultralytics/models/yolo/classify/val.py +216 -0
  192. ultralytics/models/yolo/detect/__init__.py +7 -0
  193. ultralytics/models/yolo/detect/predict.py +122 -0
  194. ultralytics/models/yolo/detect/train.py +227 -0
  195. ultralytics/models/yolo/detect/val.py +507 -0
  196. ultralytics/models/yolo/model.py +430 -0
  197. ultralytics/models/yolo/obb/__init__.py +7 -0
  198. ultralytics/models/yolo/obb/predict.py +56 -0
  199. ultralytics/models/yolo/obb/train.py +79 -0
  200. ultralytics/models/yolo/obb/val.py +302 -0
  201. ultralytics/models/yolo/pose/__init__.py +7 -0
  202. ultralytics/models/yolo/pose/predict.py +65 -0
  203. ultralytics/models/yolo/pose/train.py +110 -0
  204. ultralytics/models/yolo/pose/val.py +248 -0
  205. ultralytics/models/yolo/segment/__init__.py +7 -0
  206. ultralytics/models/yolo/segment/predict.py +109 -0
  207. ultralytics/models/yolo/segment/train.py +69 -0
  208. ultralytics/models/yolo/segment/val.py +307 -0
  209. ultralytics/models/yolo/world/__init__.py +5 -0
  210. ultralytics/models/yolo/world/train.py +173 -0
  211. ultralytics/models/yolo/world/train_world.py +178 -0
  212. ultralytics/models/yolo/yoloe/__init__.py +22 -0
  213. ultralytics/models/yolo/yoloe/predict.py +162 -0
  214. ultralytics/models/yolo/yoloe/train.py +287 -0
  215. ultralytics/models/yolo/yoloe/train_seg.py +122 -0
  216. ultralytics/models/yolo/yoloe/val.py +206 -0
  217. ultralytics/nn/__init__.py +27 -0
  218. ultralytics/nn/autobackend.py +964 -0
  219. ultralytics/nn/modules/__init__.py +182 -0
  220. ultralytics/nn/modules/activation.py +54 -0
  221. ultralytics/nn/modules/block.py +1947 -0
  222. ultralytics/nn/modules/conv.py +669 -0
  223. ultralytics/nn/modules/head.py +1183 -0
  224. ultralytics/nn/modules/transformer.py +793 -0
  225. ultralytics/nn/modules/utils.py +159 -0
  226. ultralytics/nn/tasks.py +1768 -0
  227. ultralytics/nn/text_model.py +356 -0
  228. ultralytics/py.typed +1 -0
  229. ultralytics/solutions/__init__.py +41 -0
  230. ultralytics/solutions/ai_gym.py +108 -0
  231. ultralytics/solutions/analytics.py +264 -0
  232. ultralytics/solutions/config.py +107 -0
  233. ultralytics/solutions/distance_calculation.py +123 -0
  234. ultralytics/solutions/heatmap.py +125 -0
  235. ultralytics/solutions/instance_segmentation.py +86 -0
  236. ultralytics/solutions/object_blurrer.py +89 -0
  237. ultralytics/solutions/object_counter.py +190 -0
  238. ultralytics/solutions/object_cropper.py +87 -0
  239. ultralytics/solutions/parking_management.py +280 -0
  240. ultralytics/solutions/queue_management.py +93 -0
  241. ultralytics/solutions/region_counter.py +133 -0
  242. ultralytics/solutions/security_alarm.py +151 -0
  243. ultralytics/solutions/similarity_search.py +219 -0
  244. ultralytics/solutions/solutions.py +828 -0
  245. ultralytics/solutions/speed_estimation.py +114 -0
  246. ultralytics/solutions/streamlit_inference.py +260 -0
  247. ultralytics/solutions/templates/similarity-search.html +156 -0
  248. ultralytics/solutions/trackzone.py +88 -0
  249. ultralytics/solutions/vision_eye.py +67 -0
  250. ultralytics/trackers/__init__.py +7 -0
  251. ultralytics/trackers/basetrack.py +115 -0
  252. ultralytics/trackers/bot_sort.py +257 -0
  253. ultralytics/trackers/byte_tracker.py +469 -0
  254. ultralytics/trackers/track.py +116 -0
  255. ultralytics/trackers/utils/__init__.py +1 -0
  256. ultralytics/trackers/utils/gmc.py +339 -0
  257. ultralytics/trackers/utils/kalman_filter.py +482 -0
  258. ultralytics/trackers/utils/matching.py +154 -0
  259. ultralytics/utils/__init__.py +1450 -0
  260. ultralytics/utils/autobatch.py +118 -0
  261. ultralytics/utils/autodevice.py +205 -0
  262. ultralytics/utils/benchmarks.py +728 -0
  263. ultralytics/utils/callbacks/__init__.py +5 -0
  264. ultralytics/utils/callbacks/base.py +233 -0
  265. ultralytics/utils/callbacks/clearml.py +146 -0
  266. ultralytics/utils/callbacks/comet.py +625 -0
  267. ultralytics/utils/callbacks/dvc.py +197 -0
  268. ultralytics/utils/callbacks/hub.py +110 -0
  269. ultralytics/utils/callbacks/mlflow.py +134 -0
  270. ultralytics/utils/callbacks/neptune.py +126 -0
  271. ultralytics/utils/callbacks/platform.py +453 -0
  272. ultralytics/utils/callbacks/raytune.py +42 -0
  273. ultralytics/utils/callbacks/tensorboard.py +123 -0
  274. ultralytics/utils/callbacks/wb.py +188 -0
  275. ultralytics/utils/checks.py +1020 -0
  276. ultralytics/utils/cpu.py +85 -0
  277. ultralytics/utils/dist.py +123 -0
  278. ultralytics/utils/downloads.py +529 -0
  279. ultralytics/utils/errors.py +35 -0
  280. ultralytics/utils/events.py +113 -0
  281. ultralytics/utils/export/__init__.py +7 -0
  282. ultralytics/utils/export/engine.py +237 -0
  283. ultralytics/utils/export/imx.py +325 -0
  284. ultralytics/utils/export/tensorflow.py +231 -0
  285. ultralytics/utils/files.py +219 -0
  286. ultralytics/utils/git.py +137 -0
  287. ultralytics/utils/instance.py +484 -0
  288. ultralytics/utils/logger.py +506 -0
  289. ultralytics/utils/loss.py +849 -0
  290. ultralytics/utils/metrics.py +1563 -0
  291. ultralytics/utils/nms.py +337 -0
  292. ultralytics/utils/ops.py +664 -0
  293. ultralytics/utils/patches.py +201 -0
  294. ultralytics/utils/plotting.py +1047 -0
  295. ultralytics/utils/tal.py +404 -0
  296. ultralytics/utils/torch_utils.py +984 -0
  297. ultralytics/utils/tqdm.py +443 -0
  298. ultralytics/utils/triton.py +112 -0
  299. ultralytics/utils/tuner.py +168 -0
@@ -0,0 +1,435 @@
1
+ # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
+
3
+ from __future__ import annotations
4
+
5
+ import glob
6
+ import math
7
+ import os
8
+ import random
9
+ from copy import deepcopy
10
+ from multiprocessing.pool import ThreadPool
11
+ from pathlib import Path
12
+ from typing import Any
13
+
14
+ import cv2
15
+ import numpy as np
16
+ from torch.utils.data import Dataset
17
+
18
+ from ultralytics.data.utils import FORMATS_HELP_MSG, HELP_URL, IMG_FORMATS, check_file_speeds
19
+ from ultralytics.utils import DEFAULT_CFG, LOCAL_RANK, LOGGER, NUM_THREADS, TQDM
20
+ from ultralytics.utils.patches import imread
21
+
22
+
23
+ class BaseDataset(Dataset):
24
+ """Base dataset class for loading and processing image data.
25
+
26
+ This class provides core functionality for loading images, caching, and preparing data for training and inference in
27
+ object detection tasks.
28
+
29
+ Attributes:
30
+ img_path (str): Path to the folder containing images.
31
+ imgsz (int): Target image size for resizing.
32
+ augment (bool): Whether to apply data augmentation.
33
+ single_cls (bool): Whether to treat all objects as a single class.
34
+ prefix (str): Prefix to print in log messages.
35
+ fraction (float): Fraction of dataset to utilize.
36
+ channels (int): Number of channels in the images (1 for grayscale, 3 for color). Color images loaded with OpenCV
37
+ are in BGR channel order.
38
+ cv2_flag (int): OpenCV flag for reading images.
39
+ im_files (list[str]): List of image file paths.
40
+ labels (list[dict]): List of label data dictionaries.
41
+ ni (int): Number of images in the dataset.
42
+ rect (bool): Whether to use rectangular training.
43
+ batch_size (int): Size of batches.
44
+ stride (int): Stride used in the model.
45
+ pad (float): Padding value.
46
+ buffer (list): Buffer for mosaic images.
47
+ max_buffer_length (int): Maximum buffer size.
48
+ ims (list): List of loaded images.
49
+ im_hw0 (list): List of original image dimensions (h, w).
50
+ im_hw (list): List of resized image dimensions (h, w).
51
+ npy_files (list[Path]): List of numpy file paths.
52
+ cache (str): Cache images to RAM or disk during training.
53
+ transforms (callable): Image transformation function.
54
+ batch_shapes (np.ndarray): Batch shapes for rectangular training.
55
+ batch (np.ndarray): Batch index of each image.
56
+
57
+ Methods:
58
+ get_img_files: Read image files from the specified path.
59
+ update_labels: Update labels to include only specified classes.
60
+ load_image: Load an image from the dataset.
61
+ cache_images: Cache images to memory or disk.
62
+ cache_images_to_disk: Save an image as an *.npy file for faster loading.
63
+ check_cache_disk: Check image caching requirements vs available disk space.
64
+ check_cache_ram: Check image caching requirements vs available memory.
65
+ set_rectangle: Set the shape of bounding boxes as rectangles.
66
+ get_image_and_label: Get and return label information from the dataset.
67
+ update_labels_info: Custom label format method to be implemented by subclasses.
68
+ build_transforms: Build transformation pipeline to be implemented by subclasses.
69
+ get_labels: Get labels method to be implemented by subclasses.
70
+ """
71
+
72
+ def __init__(
73
+ self,
74
+ img_path: str | list[str],
75
+ imgsz: int = 640,
76
+ cache: bool | str = False,
77
+ augment: bool = True,
78
+ hyp: dict[str, Any] = DEFAULT_CFG,
79
+ prefix: str = "",
80
+ rect: bool = False,
81
+ batch_size: int = 16,
82
+ stride: int = 32,
83
+ pad: float = 0.5,
84
+ single_cls: bool = False,
85
+ classes: list[int] | None = None,
86
+ fraction: float = 1.0,
87
+ channels: int = 3,
88
+ ):
89
+ """Initialize BaseDataset with given configuration and options.
90
+
91
+ Args:
92
+ img_path (str | list[str]): Path to the folder containing images or list of image paths.
93
+ imgsz (int): Image size for resizing.
94
+ cache (bool | str): Cache images to RAM or disk during training.
95
+ augment (bool): If True, data augmentation is applied.
96
+ hyp (dict[str, Any]): Hyperparameters to apply data augmentation.
97
+ prefix (str): Prefix to print in log messages.
98
+ rect (bool): If True, rectangular training is used.
99
+ batch_size (int): Size of batches.
100
+ stride (int): Stride used in the model.
101
+ pad (float): Padding value.
102
+ single_cls (bool): If True, single class training is used.
103
+ classes (list[int], optional): List of included classes.
104
+ fraction (float): Fraction of dataset to utilize.
105
+ channels (int): Number of channels in the images (1 for grayscale, 3 for color). Color images loaded with
106
+ OpenCV are in BGR channel order.
107
+ """
108
+ super().__init__()
109
+ self.img_path = img_path
110
+ self.imgsz = imgsz
111
+ self.augment = augment
112
+ self.single_cls = single_cls
113
+ self.prefix = prefix
114
+ self.fraction = fraction
115
+ self.channels = channels
116
+ self.cv2_flag = cv2.IMREAD_GRAYSCALE if channels == 1 else cv2.IMREAD_COLOR
117
+ self.im_files = self.get_img_files(self.img_path)
118
+ self.labels = self.get_labels()
119
+ self.update_labels(include_class=classes) # single_cls and include_class
120
+ self.ni = len(self.labels) # number of images
121
+ self.rect = rect
122
+ self.batch_size = batch_size
123
+ self.stride = stride
124
+ self.pad = pad
125
+ if self.rect:
126
+ assert self.batch_size is not None
127
+ self.set_rectangle()
128
+
129
+ # Buffer thread for mosaic images
130
+ self.buffer = [] # buffer size = batch size
131
+ self.max_buffer_length = min((self.ni, self.batch_size * 8, 1000)) if self.augment else 0
132
+
133
+ # Cache images (options are cache = True, False, None, "ram", "disk")
134
+ self.ims, self.im_hw0, self.im_hw = [None] * self.ni, [None] * self.ni, [None] * self.ni
135
+ self.npy_files = [Path(f).with_suffix(".npy") for f in self.im_files]
136
+ self.cache = cache.lower() if isinstance(cache, str) else "ram" if cache is True else None
137
+ if self.cache == "ram" and self.check_cache_ram():
138
+ if hyp.deterministic:
139
+ LOGGER.warning(
140
+ "cache='ram' may produce non-deterministic training results. "
141
+ "Consider cache='disk' as a deterministic alternative if your disk space allows."
142
+ )
143
+ self.cache_images()
144
+ elif self.cache == "disk" and self.check_cache_disk():
145
+ self.cache_images()
146
+
147
+ # Transforms
148
+ self.transforms = self.build_transforms(hyp=hyp)
149
+
150
+ def get_img_files(self, img_path: str | list[str]) -> list[str]:
151
+ """Read image files from the specified path.
152
+
153
+ Args:
154
+ img_path (str | list[str]): Path or list of paths to image directories or files.
155
+
156
+ Returns:
157
+ (list[str]): List of image file paths.
158
+
159
+ Raises:
160
+ FileNotFoundError: If no images are found or the path doesn't exist.
161
+ """
162
+ try:
163
+ f = [] # image files
164
+ for p in img_path if isinstance(img_path, list) else [img_path]:
165
+ p = Path(p) # os-agnostic
166
+ if p.is_dir(): # dir
167
+ f += glob.glob(str(p / "**" / "*.*"), recursive=True)
168
+ # F = list(p.rglob('*.*')) # pathlib
169
+ elif p.is_file(): # file
170
+ with open(p, encoding="utf-8") as t:
171
+ t = t.read().strip().splitlines()
172
+ parent = str(p.parent) + os.sep
173
+ f += [x.replace("./", parent) if x.startswith("./") else x for x in t] # local to global path
174
+ # F += [p.parent / x.lstrip(os.sep) for x in t] # local to global path (pathlib)
175
+ else:
176
+ raise FileNotFoundError(f"{self.prefix}{p} does not exist")
177
+ im_files = sorted(x.replace("/", os.sep) for x in f if x.rpartition(".")[-1].lower() in IMG_FORMATS)
178
+ # self.img_files = sorted([x for x in f if x.suffix[1:].lower() in IMG_FORMATS]) # pathlib
179
+ assert im_files, f"{self.prefix}No images found in {img_path}. {FORMATS_HELP_MSG}"
180
+ except Exception as e:
181
+ raise FileNotFoundError(f"{self.prefix}Error loading data from {img_path}\n{HELP_URL}") from e
182
+ if self.fraction < 1:
183
+ im_files = im_files[: round(len(im_files) * self.fraction)] # retain a fraction of the dataset
184
+ check_file_speeds(im_files, prefix=self.prefix) # check image read speeds
185
+ return im_files
186
+
187
+ def update_labels(self, include_class: list[int] | None) -> None:
188
+ """Update labels to include only specified classes.
189
+
190
+ Args:
191
+ include_class (list[int], optional): List of classes to include. If None, all classes are included.
192
+ """
193
+ include_class_array = np.array(include_class).reshape(1, -1)
194
+ for i in range(len(self.labels)):
195
+ if include_class is not None:
196
+ cls = self.labels[i]["cls"]
197
+ bboxes = self.labels[i]["bboxes"]
198
+ segments = self.labels[i]["segments"]
199
+ keypoints = self.labels[i]["keypoints"]
200
+ j = (cls == include_class_array).any(1)
201
+ self.labels[i]["cls"] = cls[j]
202
+ self.labels[i]["bboxes"] = bboxes[j]
203
+ if segments:
204
+ self.labels[i]["segments"] = [segments[si] for si, idx in enumerate(j) if idx]
205
+ if keypoints is not None:
206
+ self.labels[i]["keypoints"] = keypoints[j]
207
+ if self.single_cls:
208
+ self.labels[i]["cls"][:, 0] = 0
209
+
210
+ def load_image(self, i: int, rect_mode: bool = True) -> tuple[np.ndarray, tuple[int, int], tuple[int, int]]:
211
+ """Load an image from dataset index 'i'.
212
+
213
+ Args:
214
+ i (int): Index of the image to load.
215
+ rect_mode (bool): Whether to use rectangular resizing.
216
+
217
+ Returns:
218
+ im (np.ndarray): Loaded image as a NumPy array.
219
+ hw_original (tuple[int, int]): Original image dimensions in (height, width) format.
220
+ hw_resized (tuple[int, int]): Resized image dimensions in (height, width) format.
221
+
222
+ Raises:
223
+ FileNotFoundError: If the image file is not found.
224
+ """
225
+ im, f, fn = self.ims[i], self.im_files[i], self.npy_files[i]
226
+ if im is None: # not cached in RAM
227
+ if fn.exists(): # load npy
228
+ try:
229
+ im = np.load(fn)
230
+ except Exception as e:
231
+ LOGGER.warning(f"{self.prefix}Removing corrupt *.npy image file {fn} due to: {e}")
232
+ Path(fn).unlink(missing_ok=True)
233
+ im = imread(f, flags=self.cv2_flag) # BGR
234
+ else: # read image
235
+ im = imread(f, flags=self.cv2_flag) # BGR
236
+ if im is None:
237
+ raise FileNotFoundError(f"Image Not Found {f}")
238
+
239
+ h0, w0 = im.shape[:2] # orig hw
240
+ if rect_mode: # resize long side to imgsz while maintaining aspect ratio
241
+ r = self.imgsz / max(h0, w0) # ratio
242
+ if r != 1: # if sizes are not equal
243
+ w, h = (min(math.ceil(w0 * r), self.imgsz), min(math.ceil(h0 * r), self.imgsz))
244
+ im = cv2.resize(im, (w, h), interpolation=cv2.INTER_LINEAR)
245
+ elif not (h0 == w0 == self.imgsz): # resize by stretching image to square imgsz
246
+ im = cv2.resize(im, (self.imgsz, self.imgsz), interpolation=cv2.INTER_LINEAR)
247
+ if im.ndim == 2:
248
+ im = im[..., None]
249
+
250
+ # Add to buffer if training with augmentations
251
+ if self.augment:
252
+ self.ims[i], self.im_hw0[i], self.im_hw[i] = im, (h0, w0), im.shape[:2] # im, hw_original, hw_resized
253
+ self.buffer.append(i)
254
+ if 1 < len(self.buffer) >= self.max_buffer_length: # prevent empty buffer
255
+ j = self.buffer.pop(0)
256
+ if self.cache != "ram":
257
+ self.ims[j], self.im_hw0[j], self.im_hw[j] = None, None, None
258
+
259
+ return im, (h0, w0), im.shape[:2]
260
+
261
+ return self.ims[i], self.im_hw0[i], self.im_hw[i]
262
+
263
+ def cache_images(self) -> None:
264
+ """Cache images to memory or disk for faster training."""
265
+ b, gb = 0, 1 << 30 # bytes of cached images, bytes per gigabytes
266
+ fcn, storage = (self.cache_images_to_disk, "Disk") if self.cache == "disk" else (self.load_image, "RAM")
267
+ with ThreadPool(NUM_THREADS) as pool:
268
+ results = pool.imap(fcn, range(self.ni))
269
+ pbar = TQDM(enumerate(results), total=self.ni, disable=LOCAL_RANK > 0)
270
+ for i, x in pbar:
271
+ if self.cache == "disk":
272
+ b += self.npy_files[i].stat().st_size
273
+ else: # 'ram'
274
+ self.ims[i], self.im_hw0[i], self.im_hw[i] = x # im, hw_orig, hw_resized = load_image(self, i)
275
+ b += self.ims[i].nbytes
276
+ pbar.desc = f"{self.prefix}Caching images ({b / gb:.1f}GB {storage})"
277
+ pbar.close()
278
+
279
+ def cache_images_to_disk(self, i: int) -> None:
280
+ """Save an image as an *.npy file for faster loading."""
281
+ f = self.npy_files[i]
282
+ if not f.exists():
283
+ np.save(f.as_posix(), imread(self.im_files[i]), allow_pickle=False)
284
+
285
+ def check_cache_disk(self, safety_margin: float = 0.5) -> bool:
286
+ """Check if there's enough disk space for caching images.
287
+
288
+ Args:
289
+ safety_margin (float): Safety margin factor for disk space calculation.
290
+
291
+ Returns:
292
+ (bool): True if there's enough disk space, False otherwise.
293
+ """
294
+ import shutil
295
+
296
+ b, gb = 0, 1 << 30 # bytes of cached images, bytes per gigabytes
297
+ n = min(self.ni, 30) # extrapolate from 30 random images
298
+ for _ in range(n):
299
+ im_file = random.choice(self.im_files)
300
+ im = imread(im_file)
301
+ if im is None:
302
+ continue
303
+ b += im.nbytes
304
+ if not os.access(Path(im_file).parent, os.W_OK):
305
+ self.cache = None
306
+ LOGGER.warning(f"{self.prefix}Skipping caching images to disk, directory not writable")
307
+ return False
308
+ disk_required = b * self.ni / n * (1 + safety_margin) # bytes required to cache dataset to disk
309
+ total, _used, free = shutil.disk_usage(Path(self.im_files[0]).parent)
310
+ if disk_required > free:
311
+ self.cache = None
312
+ LOGGER.warning(
313
+ f"{self.prefix}{disk_required / gb:.1f}GB disk space required, "
314
+ f"with {int(safety_margin * 100)}% safety margin but only "
315
+ f"{free / gb:.1f}/{total / gb:.1f}GB free, not caching images to disk"
316
+ )
317
+ return False
318
+ return True
319
+
320
+ def check_cache_ram(self, safety_margin: float = 0.5) -> bool:
321
+ """Check if there's enough RAM for caching images.
322
+
323
+ Args:
324
+ safety_margin (float): Safety margin factor for RAM calculation.
325
+
326
+ Returns:
327
+ (bool): True if there's enough RAM, False otherwise.
328
+ """
329
+ b, gb = 0, 1 << 30 # bytes of cached images, bytes per gigabytes
330
+ n = min(self.ni, 30) # extrapolate from 30 random images
331
+ for _ in range(n):
332
+ im = imread(random.choice(self.im_files)) # sample image
333
+ if im is None:
334
+ continue
335
+ ratio = self.imgsz / max(im.shape[0], im.shape[1]) # max(h, w) # ratio
336
+ b += im.nbytes * ratio**2
337
+ mem_required = b * self.ni / n * (1 + safety_margin) # GB required to cache dataset into RAM
338
+ mem = __import__("psutil").virtual_memory()
339
+ if mem_required > mem.available:
340
+ self.cache = None
341
+ LOGGER.warning(
342
+ f"{self.prefix}{mem_required / gb:.1f}GB RAM required to cache images "
343
+ f"with {int(safety_margin * 100)}% safety margin but only "
344
+ f"{mem.available / gb:.1f}/{mem.total / gb:.1f}GB available, not caching images"
345
+ )
346
+ return False
347
+ return True
348
+
349
+ def set_rectangle(self) -> None:
350
+ """Set the shape of bounding boxes for YOLO detections as rectangles."""
351
+ bi = np.floor(np.arange(self.ni) / self.batch_size).astype(int) # batch index
352
+ nb = bi[-1] + 1 # number of batches
353
+
354
+ s = np.array([x.pop("shape") for x in self.labels]) # hw
355
+ ar = s[:, 0] / s[:, 1] # aspect ratio
356
+ irect = ar.argsort()
357
+ self.im_files = [self.im_files[i] for i in irect]
358
+ self.labels = [self.labels[i] for i in irect]
359
+ ar = ar[irect]
360
+
361
+ # Set training image shapes
362
+ shapes = [[1, 1]] * nb
363
+ for i in range(nb):
364
+ ari = ar[bi == i]
365
+ mini, maxi = ari.min(), ari.max()
366
+ if maxi < 1:
367
+ shapes[i] = [maxi, 1]
368
+ elif mini > 1:
369
+ shapes[i] = [1, 1 / mini]
370
+
371
+ self.batch_shapes = np.ceil(np.array(shapes) * self.imgsz / self.stride + self.pad).astype(int) * self.stride
372
+ self.batch = bi # batch index of image
373
+
374
+ def __getitem__(self, index: int) -> dict[str, Any]:
375
+ """Return transformed label information for given index."""
376
+ return self.transforms(self.get_image_and_label(index))
377
+
378
+ def get_image_and_label(self, index: int) -> dict[str, Any]:
379
+ """Get and return label information from the dataset.
380
+
381
+ Args:
382
+ index (int): Index of the image to retrieve.
383
+
384
+ Returns:
385
+ (dict[str, Any]): Label dictionary with image and metadata.
386
+ """
387
+ label = deepcopy(self.labels[index]) # requires deepcopy() https://github.com/ultralytics/ultralytics/pull/1948
388
+ label.pop("shape", None) # shape is for rect, remove it
389
+ label["img"], label["ori_shape"], label["resized_shape"] = self.load_image(index)
390
+ label["ratio_pad"] = (
391
+ label["resized_shape"][0] / label["ori_shape"][0],
392
+ label["resized_shape"][1] / label["ori_shape"][1],
393
+ ) # for evaluation
394
+ if self.rect:
395
+ label["rect_shape"] = self.batch_shapes[self.batch[index]]
396
+ return self.update_labels_info(label)
397
+
398
+ def __len__(self) -> int:
399
+ """Return the length of the labels list for the dataset."""
400
+ return len(self.labels)
401
+
402
+ def update_labels_info(self, label: dict[str, Any]) -> dict[str, Any]:
403
+ """Custom your label format here."""
404
+ return label
405
+
406
+ def build_transforms(self, hyp: dict[str, Any] | None = None):
407
+ """Users can customize augmentations here.
408
+
409
+ Examples:
410
+ >>> if self.augment:
411
+ ... # Training transforms
412
+ ... return Compose([])
413
+ >>> else:
414
+ ... # Val transforms
415
+ ... return Compose([])
416
+ """
417
+ raise NotImplementedError
418
+
419
+ def get_labels(self) -> list[dict[str, Any]]:
420
+ """Users can customize their own format here.
421
+
422
+ Examples:
423
+ Ensure output is a dictionary with the following keys:
424
+ >>> dict(
425
+ ... im_file=im_file,
426
+ ... shape=shape, # format: (height, width)
427
+ ... cls=cls,
428
+ ... bboxes=bboxes, # xywh
429
+ ... segments=segments, # xy
430
+ ... keypoints=keypoints, # xy
431
+ ... normalized=True, # or False
432
+ ... bbox_format="xyxy", # or xywh, ltwh
433
+ ... )
434
+ """
435
+ raise NotImplementedError