ultralytics 8.3.9__py3-none-any.whl → 8.3.10__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.
- ultralytics/__init__.py +1 -1
- ultralytics/data/loaders.py +162 -81
- ultralytics/data/utils.py +1 -1
- ultralytics/engine/predictor.py +1 -1
- ultralytics/nn/modules/head.py +9 -9
- ultralytics/utils/checks.py +9 -6
- {ultralytics-8.3.9.dist-info → ultralytics-8.3.10.dist-info}/METADATA +1 -1
- {ultralytics-8.3.9.dist-info → ultralytics-8.3.10.dist-info}/RECORD +12 -13
- tests/test_explorer.py +0 -66
- {ultralytics-8.3.9.dist-info → ultralytics-8.3.10.dist-info}/LICENSE +0 -0
- {ultralytics-8.3.9.dist-info → ultralytics-8.3.10.dist-info}/WHEEL +0 -0
- {ultralytics-8.3.9.dist-info → ultralytics-8.3.10.dist-info}/entry_points.txt +0 -0
- {ultralytics-8.3.9.dist-info → ultralytics-8.3.10.dist-info}/top_level.txt +0 -0
ultralytics/__init__.py
CHANGED
ultralytics/data/loaders.py
CHANGED
|
@@ -18,11 +18,29 @@ from PIL import Image
|
|
|
18
18
|
from ultralytics.data.utils import FORMATS_HELP_MSG, IMG_FORMATS, VID_FORMATS
|
|
19
19
|
from ultralytics.utils import IS_COLAB, IS_KAGGLE, LOGGER, ops
|
|
20
20
|
from ultralytics.utils.checks import check_requirements
|
|
21
|
+
from ultralytics.utils.patches import imread
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
@dataclass
|
|
24
25
|
class SourceTypes:
|
|
25
|
-
"""
|
|
26
|
+
"""
|
|
27
|
+
Class to represent various types of input sources for predictions.
|
|
28
|
+
|
|
29
|
+
This class uses dataclass to define boolean flags for different types of input sources that can be used for
|
|
30
|
+
making predictions with YOLO models.
|
|
31
|
+
|
|
32
|
+
Attributes:
|
|
33
|
+
stream (bool): Flag indicating if the input source is a video stream.
|
|
34
|
+
screenshot (bool): Flag indicating if the input source is a screenshot.
|
|
35
|
+
from_img (bool): Flag indicating if the input source is an image file.
|
|
36
|
+
|
|
37
|
+
Examples:
|
|
38
|
+
>>> source_types = SourceTypes(stream=True, screenshot=False, from_img=False)
|
|
39
|
+
>>> print(source_types.stream)
|
|
40
|
+
True
|
|
41
|
+
>>> print(source_types.from_img)
|
|
42
|
+
False
|
|
43
|
+
"""
|
|
26
44
|
|
|
27
45
|
stream: bool = False
|
|
28
46
|
screenshot: bool = False
|
|
@@ -32,38 +50,47 @@ class SourceTypes:
|
|
|
32
50
|
|
|
33
51
|
class LoadStreams:
|
|
34
52
|
"""
|
|
35
|
-
Stream Loader for various types of video streams
|
|
53
|
+
Stream Loader for various types of video streams.
|
|
54
|
+
|
|
55
|
+
Supports RTSP, RTMP, HTTP, and TCP streams. This class handles the loading and processing of multiple video
|
|
56
|
+
streams simultaneously, making it suitable for real-time video analysis tasks.
|
|
36
57
|
|
|
37
58
|
Attributes:
|
|
38
|
-
sources (str): The source input paths or URLs for the video streams.
|
|
39
|
-
vid_stride (int): Video frame-rate stride
|
|
40
|
-
buffer (bool): Whether to buffer input streams
|
|
59
|
+
sources (List[str]): The source input paths or URLs for the video streams.
|
|
60
|
+
vid_stride (int): Video frame-rate stride.
|
|
61
|
+
buffer (bool): Whether to buffer input streams.
|
|
41
62
|
running (bool): Flag to indicate if the streaming thread is running.
|
|
42
63
|
mode (str): Set to 'stream' indicating real-time capture.
|
|
43
|
-
imgs (
|
|
44
|
-
fps (
|
|
45
|
-
frames (
|
|
46
|
-
threads (
|
|
47
|
-
shape (
|
|
48
|
-
caps (
|
|
64
|
+
imgs (List[List[np.ndarray]]): List of image frames for each stream.
|
|
65
|
+
fps (List[float]): List of FPS for each stream.
|
|
66
|
+
frames (List[int]): List of total frames for each stream.
|
|
67
|
+
threads (List[Thread]): List of threads for each stream.
|
|
68
|
+
shape (List[Tuple[int, int, int]]): List of shapes for each stream.
|
|
69
|
+
caps (List[cv2.VideoCapture]): List of cv2.VideoCapture objects for each stream.
|
|
49
70
|
bs (int): Batch size for processing.
|
|
50
71
|
|
|
51
72
|
Methods:
|
|
52
|
-
__init__: Initialize the stream loader.
|
|
53
73
|
update: Read stream frames in daemon thread.
|
|
54
74
|
close: Close stream loader and release resources.
|
|
55
75
|
__iter__: Returns an iterator object for the class.
|
|
56
76
|
__next__: Returns source paths, transformed, and original images for processing.
|
|
57
77
|
__len__: Return the length of the sources object.
|
|
58
78
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
79
|
+
Examples:
|
|
80
|
+
>>> stream_loader = LoadStreams("rtsp://example.com/stream1.mp4")
|
|
81
|
+
>>> for sources, imgs, _ in stream_loader:
|
|
82
|
+
... # Process the images
|
|
83
|
+
... pass
|
|
84
|
+
>>> stream_loader.close()
|
|
85
|
+
|
|
86
|
+
Notes:
|
|
87
|
+
- The class uses threading to efficiently load frames from multiple streams simultaneously.
|
|
88
|
+
- It automatically handles YouTube links, converting them to the best available stream URL.
|
|
89
|
+
- The class implements a buffer system to manage frame storage and retrieval.
|
|
63
90
|
"""
|
|
64
91
|
|
|
65
92
|
def __init__(self, sources="file.streams", vid_stride=1, buffer=False):
|
|
66
|
-
"""Initialize
|
|
93
|
+
"""Initialize stream loader for multiple video sources, supporting various stream types."""
|
|
67
94
|
torch.backends.cudnn.benchmark = True # faster for fixed-size inference
|
|
68
95
|
self.buffer = buffer # buffer input streams
|
|
69
96
|
self.running = True # running flag for Thread
|
|
@@ -114,7 +141,7 @@ class LoadStreams:
|
|
|
114
141
|
LOGGER.info("") # newline
|
|
115
142
|
|
|
116
143
|
def update(self, i, cap, stream):
|
|
117
|
-
"""Read stream
|
|
144
|
+
"""Read stream frames in daemon thread and update image buffer."""
|
|
118
145
|
n, f = 0, self.frames[i] # frame number, frame array
|
|
119
146
|
while self.running and cap.isOpened() and n < (f - 1):
|
|
120
147
|
if len(self.imgs[i]) < 30: # keep a <=30-image buffer
|
|
@@ -134,7 +161,7 @@ class LoadStreams:
|
|
|
134
161
|
time.sleep(0.01) # wait until the buffer is empty
|
|
135
162
|
|
|
136
163
|
def close(self):
|
|
137
|
-
"""
|
|
164
|
+
"""Terminates stream loader, stops threads, and releases video capture resources."""
|
|
138
165
|
self.running = False # stop flag for Thread
|
|
139
166
|
for thread in self.threads:
|
|
140
167
|
if thread.is_alive():
|
|
@@ -152,7 +179,7 @@ class LoadStreams:
|
|
|
152
179
|
return self
|
|
153
180
|
|
|
154
181
|
def __next__(self):
|
|
155
|
-
"""Returns
|
|
182
|
+
"""Returns the next batch of frames from multiple video streams for processing."""
|
|
156
183
|
self.count += 1
|
|
157
184
|
|
|
158
185
|
images = []
|
|
@@ -179,16 +206,16 @@ class LoadStreams:
|
|
|
179
206
|
return self.sources, images, [""] * self.bs
|
|
180
207
|
|
|
181
208
|
def __len__(self):
|
|
182
|
-
"""Return the
|
|
209
|
+
"""Return the number of video streams in the LoadStreams object."""
|
|
183
210
|
return self.bs # 1E12 frames = 32 streams at 30 FPS for 30 years
|
|
184
211
|
|
|
185
212
|
|
|
186
213
|
class LoadScreenshots:
|
|
187
214
|
"""
|
|
188
|
-
|
|
215
|
+
Ultralytics screenshot dataloader for capturing and processing screen images.
|
|
189
216
|
|
|
190
|
-
This class manages the loading of screenshot images for processing with
|
|
191
|
-
|
|
217
|
+
This class manages the loading of screenshot images for processing with YOLO. It is suitable for use with
|
|
218
|
+
`yolo predict source=screen`.
|
|
192
219
|
|
|
193
220
|
Attributes:
|
|
194
221
|
source (str): The source input indicating which screen to capture.
|
|
@@ -201,15 +228,21 @@ class LoadScreenshots:
|
|
|
201
228
|
frame (int): Counter for captured frames.
|
|
202
229
|
sct (mss.mss): Screen capture object from `mss` library.
|
|
203
230
|
bs (int): Batch size, set to 1.
|
|
204
|
-
|
|
231
|
+
fps (int): Frames per second, set to 30.
|
|
232
|
+
monitor (Dict[str, int]): Monitor configuration details.
|
|
205
233
|
|
|
206
234
|
Methods:
|
|
207
235
|
__iter__: Returns an iterator object.
|
|
208
236
|
__next__: Captures the next screenshot and returns it.
|
|
237
|
+
|
|
238
|
+
Examples:
|
|
239
|
+
>>> loader = LoadScreenshots("0 100 100 640 480") # screen 0, top-left (100,100), 640x480
|
|
240
|
+
>>> for source, im, im0s, vid_cap, s in loader:
|
|
241
|
+
... print(f"Captured frame: {im.shape}")
|
|
209
242
|
"""
|
|
210
243
|
|
|
211
244
|
def __init__(self, source):
|
|
212
|
-
"""
|
|
245
|
+
"""Initialize screenshot capture with specified screen and region parameters."""
|
|
213
246
|
check_requirements("mss")
|
|
214
247
|
import mss # noqa
|
|
215
248
|
|
|
@@ -236,11 +269,11 @@ class LoadScreenshots:
|
|
|
236
269
|
self.monitor = {"left": self.left, "top": self.top, "width": self.width, "height": self.height}
|
|
237
270
|
|
|
238
271
|
def __iter__(self):
|
|
239
|
-
"""
|
|
272
|
+
"""Yields the next screenshot image from the specified screen or region for processing."""
|
|
240
273
|
return self
|
|
241
274
|
|
|
242
275
|
def __next__(self):
|
|
243
|
-
"""
|
|
276
|
+
"""Captures and returns the next screenshot as a numpy array using the mss library."""
|
|
244
277
|
im0 = np.asarray(self.sct.grab(self.monitor))[:, :, :3] # BGRA to BGR
|
|
245
278
|
s = f"screen {self.screen} (LTWH): {self.left},{self.top},{self.width},{self.height}: "
|
|
246
279
|
|
|
@@ -250,29 +283,45 @@ class LoadScreenshots:
|
|
|
250
283
|
|
|
251
284
|
class LoadImagesAndVideos:
|
|
252
285
|
"""
|
|
253
|
-
|
|
286
|
+
A class for loading and processing images and videos for YOLO object detection.
|
|
254
287
|
|
|
255
|
-
This class manages the loading and pre-processing of image and video data
|
|
256
|
-
|
|
288
|
+
This class manages the loading and pre-processing of image and video data from various sources, including
|
|
289
|
+
single image files, video files, and lists of image and video paths.
|
|
257
290
|
|
|
258
291
|
Attributes:
|
|
259
|
-
files (
|
|
292
|
+
files (List[str]): List of image and video file paths.
|
|
260
293
|
nf (int): Total number of files (images and videos).
|
|
261
|
-
video_flag (
|
|
294
|
+
video_flag (List[bool]): Flags indicating whether a file is a video (True) or an image (False).
|
|
262
295
|
mode (str): Current mode, 'image' or 'video'.
|
|
263
|
-
vid_stride (int): Stride for video frame-rate
|
|
264
|
-
bs (int): Batch size
|
|
296
|
+
vid_stride (int): Stride for video frame-rate.
|
|
297
|
+
bs (int): Batch size.
|
|
265
298
|
cap (cv2.VideoCapture): Video capture object for OpenCV.
|
|
266
299
|
frame (int): Frame counter for video.
|
|
267
300
|
frames (int): Total number of frames in the video.
|
|
268
|
-
count (int): Counter for iteration, initialized at 0 during
|
|
301
|
+
count (int): Counter for iteration, initialized at 0 during __iter__().
|
|
302
|
+
ni (int): Number of images.
|
|
269
303
|
|
|
270
304
|
Methods:
|
|
271
|
-
|
|
305
|
+
__init__: Initialize the LoadImagesAndVideos object.
|
|
306
|
+
__iter__: Returns an iterator object for VideoStream or ImageFolder.
|
|
307
|
+
__next__: Returns the next batch of images or video frames along with their paths and metadata.
|
|
308
|
+
_new_video: Creates a new video capture object for the given path.
|
|
309
|
+
__len__: Returns the number of batches in the object.
|
|
310
|
+
|
|
311
|
+
Examples:
|
|
312
|
+
>>> loader = LoadImagesAndVideos("path/to/data", batch=32, vid_stride=1)
|
|
313
|
+
>>> for paths, imgs, info in loader:
|
|
314
|
+
... # Process batch of images or video frames
|
|
315
|
+
... pass
|
|
316
|
+
|
|
317
|
+
Notes:
|
|
318
|
+
- Supports various image formats including HEIC.
|
|
319
|
+
- Handles both local files and directories.
|
|
320
|
+
- Can read from a text file containing paths to images and videos.
|
|
272
321
|
"""
|
|
273
322
|
|
|
274
323
|
def __init__(self, path, batch=1, vid_stride=1):
|
|
275
|
-
"""Initialize
|
|
324
|
+
"""Initialize dataloader for images and videos, supporting various input formats."""
|
|
276
325
|
parent = None
|
|
277
326
|
if isinstance(path, str) and Path(path).suffix == ".txt": # *.txt file with img/vid/dir on each line
|
|
278
327
|
parent = Path(path).parent
|
|
@@ -316,12 +365,12 @@ class LoadImagesAndVideos:
|
|
|
316
365
|
raise FileNotFoundError(f"No images or videos found in {p}. {FORMATS_HELP_MSG}")
|
|
317
366
|
|
|
318
367
|
def __iter__(self):
|
|
319
|
-
"""
|
|
368
|
+
"""Iterates through image/video files, yielding source paths, images, and metadata."""
|
|
320
369
|
self.count = 0
|
|
321
370
|
return self
|
|
322
371
|
|
|
323
372
|
def __next__(self):
|
|
324
|
-
"""Returns the next batch of images or video frames
|
|
373
|
+
"""Returns the next batch of images or video frames with their paths and metadata."""
|
|
325
374
|
paths, imgs, info = [], [], []
|
|
326
375
|
while len(imgs) < self.bs:
|
|
327
376
|
if self.count >= self.nf: # end of file list
|
|
@@ -336,6 +385,7 @@ class LoadImagesAndVideos:
|
|
|
336
385
|
if not self.cap or not self.cap.isOpened():
|
|
337
386
|
self._new_video(path)
|
|
338
387
|
|
|
388
|
+
success = False
|
|
339
389
|
for _ in range(self.vid_stride):
|
|
340
390
|
success = self.cap.grab()
|
|
341
391
|
if not success:
|
|
@@ -359,8 +409,19 @@ class LoadImagesAndVideos:
|
|
|
359
409
|
if self.count < self.nf:
|
|
360
410
|
self._new_video(self.files[self.count])
|
|
361
411
|
else:
|
|
412
|
+
# Handle image files (including HEIC)
|
|
362
413
|
self.mode = "image"
|
|
363
|
-
|
|
414
|
+
if path.split(".")[-1].lower() == "heic":
|
|
415
|
+
# Load HEIC image using Pillow with pillow-heif
|
|
416
|
+
check_requirements("pillow-heif")
|
|
417
|
+
|
|
418
|
+
from pillow_heif import register_heif_opener
|
|
419
|
+
|
|
420
|
+
register_heif_opener() # Register HEIF opener with Pillow
|
|
421
|
+
with Image.open(path) as img:
|
|
422
|
+
im0 = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR) # convert image to BGR nparray
|
|
423
|
+
else:
|
|
424
|
+
im0 = imread(path) # BGR
|
|
364
425
|
if im0 is None:
|
|
365
426
|
LOGGER.warning(f"WARNING ⚠️ Image Read Error {path}")
|
|
366
427
|
else:
|
|
@@ -374,7 +435,7 @@ class LoadImagesAndVideos:
|
|
|
374
435
|
return paths, imgs, info
|
|
375
436
|
|
|
376
437
|
def _new_video(self, path):
|
|
377
|
-
"""Creates a new video capture object for the given path."""
|
|
438
|
+
"""Creates a new video capture object for the given path and initializes video-related attributes."""
|
|
378
439
|
self.frame = 0
|
|
379
440
|
self.cap = cv2.VideoCapture(path)
|
|
380
441
|
self.fps = int(self.cap.get(cv2.CAP_PROP_FPS))
|
|
@@ -383,40 +444,50 @@ class LoadImagesAndVideos:
|
|
|
383
444
|
self.frames = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT) / self.vid_stride)
|
|
384
445
|
|
|
385
446
|
def __len__(self):
|
|
386
|
-
"""Returns the number of
|
|
387
|
-
return math.ceil(self.nf / self.bs) # number of
|
|
447
|
+
"""Returns the number of files (images and videos) in the dataset."""
|
|
448
|
+
return math.ceil(self.nf / self.bs) # number of batches
|
|
388
449
|
|
|
389
450
|
|
|
390
451
|
class LoadPilAndNumpy:
|
|
391
452
|
"""
|
|
392
453
|
Load images from PIL and Numpy arrays for batch processing.
|
|
393
454
|
|
|
394
|
-
This class
|
|
395
|
-
|
|
396
|
-
downstream processing.
|
|
455
|
+
This class manages loading and pre-processing of image data from both PIL and Numpy formats. It performs basic
|
|
456
|
+
validation and format conversion to ensure that the images are in the required format for downstream processing.
|
|
397
457
|
|
|
398
458
|
Attributes:
|
|
399
|
-
paths (
|
|
400
|
-
im0 (
|
|
401
|
-
mode (str): Type of data being processed,
|
|
459
|
+
paths (List[str]): List of image paths or autogenerated filenames.
|
|
460
|
+
im0 (List[np.ndarray]): List of images stored as Numpy arrays.
|
|
461
|
+
mode (str): Type of data being processed, set to 'image'.
|
|
402
462
|
bs (int): Batch size, equivalent to the length of `im0`.
|
|
403
463
|
|
|
404
464
|
Methods:
|
|
405
|
-
_single_check
|
|
465
|
+
_single_check: Validate and format a single image to a Numpy array.
|
|
466
|
+
|
|
467
|
+
Examples:
|
|
468
|
+
>>> from PIL import Image
|
|
469
|
+
>>> import numpy as np
|
|
470
|
+
>>> pil_img = Image.new("RGB", (100, 100))
|
|
471
|
+
>>> np_img = np.random.randint(0, 255, (100, 100, 3), dtype=np.uint8)
|
|
472
|
+
>>> loader = LoadPilAndNumpy([pil_img, np_img])
|
|
473
|
+
>>> paths, images, _ = next(iter(loader))
|
|
474
|
+
>>> print(f"Loaded {len(images)} images")
|
|
475
|
+
Loaded 2 images
|
|
406
476
|
"""
|
|
407
477
|
|
|
408
478
|
def __init__(self, im0):
|
|
409
|
-
"""
|
|
479
|
+
"""Initializes a loader for PIL and Numpy images, converting inputs to a standardized format."""
|
|
410
480
|
if not isinstance(im0, list):
|
|
411
481
|
im0 = [im0]
|
|
412
|
-
|
|
482
|
+
# use `image{i}.jpg` when Image.filename returns an empty path.
|
|
483
|
+
self.paths = [getattr(im, "filename", "") or f"image{i}.jpg" for i, im in enumerate(im0)]
|
|
413
484
|
self.im0 = [self._single_check(im) for im in im0]
|
|
414
485
|
self.mode = "image"
|
|
415
486
|
self.bs = len(self.im0)
|
|
416
487
|
|
|
417
488
|
@staticmethod
|
|
418
489
|
def _single_check(im):
|
|
419
|
-
"""Validate and format an image to numpy array."""
|
|
490
|
+
"""Validate and format an image to numpy array, ensuring RGB order and contiguous memory."""
|
|
420
491
|
assert isinstance(im, (Image.Image, np.ndarray)), f"Expected PIL/np.ndarray image type, but got {type(im)}"
|
|
421
492
|
if isinstance(im, Image.Image):
|
|
422
493
|
if im.mode != "RGB":
|
|
@@ -426,41 +497,48 @@ class LoadPilAndNumpy:
|
|
|
426
497
|
return im
|
|
427
498
|
|
|
428
499
|
def __len__(self):
|
|
429
|
-
"""Returns the length of the 'im0' attribute."""
|
|
500
|
+
"""Returns the length of the 'im0' attribute, representing the number of loaded images."""
|
|
430
501
|
return len(self.im0)
|
|
431
502
|
|
|
432
503
|
def __next__(self):
|
|
433
|
-
"""Returns
|
|
504
|
+
"""Returns the next batch of images, paths, and metadata for processing."""
|
|
434
505
|
if self.count == 1: # loop only once as it's batch inference
|
|
435
506
|
raise StopIteration
|
|
436
507
|
self.count += 1
|
|
437
508
|
return self.paths, self.im0, [""] * self.bs
|
|
438
509
|
|
|
439
510
|
def __iter__(self):
|
|
440
|
-
"""
|
|
511
|
+
"""Iterates through PIL/numpy images, yielding paths, raw images, and metadata for processing."""
|
|
441
512
|
self.count = 0
|
|
442
513
|
return self
|
|
443
514
|
|
|
444
515
|
|
|
445
516
|
class LoadTensor:
|
|
446
517
|
"""
|
|
447
|
-
|
|
518
|
+
A class for loading and processing tensor data for object detection tasks.
|
|
448
519
|
|
|
449
|
-
This class
|
|
520
|
+
This class handles the loading and pre-processing of image data from PyTorch tensors, preparing them for
|
|
521
|
+
further processing in object detection pipelines.
|
|
450
522
|
|
|
451
523
|
Attributes:
|
|
452
|
-
im0 (torch.Tensor): The input tensor containing the image(s).
|
|
524
|
+
im0 (torch.Tensor): The input tensor containing the image(s) with shape (B, C, H, W).
|
|
453
525
|
bs (int): Batch size, inferred from the shape of `im0`.
|
|
454
|
-
mode (str): Current mode, set to 'image'.
|
|
455
|
-
paths (
|
|
456
|
-
count (int): Counter for iteration, initialized at 0 during `__iter__()`.
|
|
526
|
+
mode (str): Current processing mode, set to 'image'.
|
|
527
|
+
paths (List[str]): List of image paths or auto-generated filenames.
|
|
457
528
|
|
|
458
529
|
Methods:
|
|
459
|
-
_single_check
|
|
530
|
+
_single_check: Validates and formats an input tensor.
|
|
531
|
+
|
|
532
|
+
Examples:
|
|
533
|
+
>>> import torch
|
|
534
|
+
>>> tensor = torch.rand(1, 3, 640, 640)
|
|
535
|
+
>>> loader = LoadTensor(tensor)
|
|
536
|
+
>>> paths, images, info = next(iter(loader))
|
|
537
|
+
>>> print(f"Processed {len(images)} images")
|
|
460
538
|
"""
|
|
461
539
|
|
|
462
540
|
def __init__(self, im0) -> None:
|
|
463
|
-
"""Initialize Tensor
|
|
541
|
+
"""Initialize LoadTensor object for processing torch.Tensor image data."""
|
|
464
542
|
self.im0 = self._single_check(im0)
|
|
465
543
|
self.bs = self.im0.shape[0]
|
|
466
544
|
self.mode = "image"
|
|
@@ -468,7 +546,7 @@ class LoadTensor:
|
|
|
468
546
|
|
|
469
547
|
@staticmethod
|
|
470
548
|
def _single_check(im, stride=32):
|
|
471
|
-
"""
|
|
549
|
+
"""Validates and formats a single image tensor, ensuring correct shape and normalization."""
|
|
472
550
|
s = (
|
|
473
551
|
f"WARNING ⚠️ torch.Tensor inputs should be BCHW i.e. shape(1, 3, 640, 640) "
|
|
474
552
|
f"divisible by stride {stride}. Input shape{tuple(im.shape)} is incompatible."
|
|
@@ -490,24 +568,24 @@ class LoadTensor:
|
|
|
490
568
|
return im
|
|
491
569
|
|
|
492
570
|
def __iter__(self):
|
|
493
|
-
"""
|
|
571
|
+
"""Yields an iterator object for iterating through tensor image data."""
|
|
494
572
|
self.count = 0
|
|
495
573
|
return self
|
|
496
574
|
|
|
497
575
|
def __next__(self):
|
|
498
|
-
"""
|
|
576
|
+
"""Yields the next batch of tensor images and metadata for processing."""
|
|
499
577
|
if self.count == 1:
|
|
500
578
|
raise StopIteration
|
|
501
579
|
self.count += 1
|
|
502
580
|
return self.paths, self.im0, [""] * self.bs
|
|
503
581
|
|
|
504
582
|
def __len__(self):
|
|
505
|
-
"""Returns the batch size."""
|
|
583
|
+
"""Returns the batch size of the tensor input."""
|
|
506
584
|
return self.bs
|
|
507
585
|
|
|
508
586
|
|
|
509
587
|
def autocast_list(source):
|
|
510
|
-
"""Merges a list of
|
|
588
|
+
"""Merges a list of sources into a list of numpy arrays or PIL images for Ultralytics prediction."""
|
|
511
589
|
files = []
|
|
512
590
|
for im in source:
|
|
513
591
|
if isinstance(im, (str, Path)): # filename or uri
|
|
@@ -527,21 +605,24 @@ def get_best_youtube_url(url, method="pytube"):
|
|
|
527
605
|
"""
|
|
528
606
|
Retrieves the URL of the best quality MP4 video stream from a given YouTube video.
|
|
529
607
|
|
|
530
|
-
This function uses the specified method to extract the video info from YouTube. It supports the following methods:
|
|
531
|
-
- "pytube": Uses the pytube library to fetch the video streams.
|
|
532
|
-
- "pafy": Uses the pafy library to fetch the video streams.
|
|
533
|
-
- "yt-dlp": Uses the yt-dlp library to fetch the video streams.
|
|
534
|
-
|
|
535
|
-
The function then finds the highest quality MP4 format that has a video codec but no audio codec, and returns the
|
|
536
|
-
URL of this video stream.
|
|
537
|
-
|
|
538
608
|
Args:
|
|
539
609
|
url (str): The URL of the YouTube video.
|
|
540
|
-
method (str): The method to use for extracting video info.
|
|
541
|
-
"
|
|
610
|
+
method (str): The method to use for extracting video info. Options are "pytube", "pafy", and "yt-dlp".
|
|
611
|
+
Defaults to "pytube".
|
|
542
612
|
|
|
543
613
|
Returns:
|
|
544
|
-
(str): The URL of the best quality MP4 video stream, or None if no suitable stream is found.
|
|
614
|
+
(str | None): The URL of the best quality MP4 video stream, or None if no suitable stream is found.
|
|
615
|
+
|
|
616
|
+
Examples:
|
|
617
|
+
>>> url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
|
|
618
|
+
>>> best_url = get_best_youtube_url(url)
|
|
619
|
+
>>> print(best_url)
|
|
620
|
+
https://rr4---sn-q4flrnek.googlevideo.com/videoplayback?expire=...
|
|
621
|
+
|
|
622
|
+
Notes:
|
|
623
|
+
- Requires additional libraries based on the chosen method: pytubefix, pafy, or yt-dlp.
|
|
624
|
+
- The function prioritizes streams with at least 1080p resolution when available.
|
|
625
|
+
- For the "yt-dlp" method, it looks for formats with video codec, no audio, and *.mp4 extension.
|
|
545
626
|
"""
|
|
546
627
|
if method == "pytube":
|
|
547
628
|
# Switched from pytube to pytubefix to resolve https://github.com/pytube/pytube/issues/1954
|
ultralytics/data/utils.py
CHANGED
|
@@ -35,7 +35,7 @@ from ultralytics.utils.downloads import download, safe_download, unzip_file
|
|
|
35
35
|
from ultralytics.utils.ops import segments2boxes
|
|
36
36
|
|
|
37
37
|
HELP_URL = "See https://docs.ultralytics.com/datasets for dataset formatting guidance."
|
|
38
|
-
IMG_FORMATS = {"bmp", "dng", "jpeg", "jpg", "mpo", "png", "tif", "tiff", "webp", "pfm"} # image suffixes
|
|
38
|
+
IMG_FORMATS = {"bmp", "dng", "jpeg", "jpg", "mpo", "png", "tif", "tiff", "webp", "pfm", "heic"} # image suffixes
|
|
39
39
|
VID_FORMATS = {"asf", "avi", "gif", "m4v", "mkv", "mov", "mp4", "mpeg", "mpg", "ts", "wmv", "webm"} # video suffixes
|
|
40
40
|
PIN_MEMORY = str(os.getenv("PIN_MEMORY", True)).lower() == "true" # global pin_memory for dataloaders
|
|
41
41
|
FORMATS_HELP_MSG = f"Supported formats are:\nimages: {IMG_FORMATS}\nvideos: {VID_FORMATS}"
|
ultralytics/engine/predictor.py
CHANGED
|
@@ -381,7 +381,7 @@ class BasePredictor:
|
|
|
381
381
|
|
|
382
382
|
# Save images
|
|
383
383
|
else:
|
|
384
|
-
cv2.imwrite(save_path, im)
|
|
384
|
+
cv2.imwrite(str(Path(save_path).with_suffix(".jpg")), im) # save to JPG for best support
|
|
385
385
|
|
|
386
386
|
def show(self, p=""):
|
|
387
387
|
"""Display an image in a window using the OpenCV imshow function."""
|
ultralytics/nn/modules/head.py
CHANGED
|
@@ -19,7 +19,7 @@ __all__ = "Detect", "Segment", "Pose", "Classify", "OBB", "RTDETRDecoder", "v10D
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class Detect(nn.Module):
|
|
22
|
-
"""
|
|
22
|
+
"""YOLO Detect head for detection models."""
|
|
23
23
|
|
|
24
24
|
dynamic = False # force grid reconstruction
|
|
25
25
|
export = False # export mode
|
|
@@ -30,7 +30,7 @@ class Detect(nn.Module):
|
|
|
30
30
|
strides = torch.empty(0) # init
|
|
31
31
|
|
|
32
32
|
def __init__(self, nc=80, ch=()):
|
|
33
|
-
"""Initializes the
|
|
33
|
+
"""Initializes the YOLO detection layer with specified number of classes and channels."""
|
|
34
34
|
super().__init__()
|
|
35
35
|
self.nc = nc # number of classes
|
|
36
36
|
self.nl = len(ch) # number of detection layers
|
|
@@ -162,7 +162,7 @@ class Detect(nn.Module):
|
|
|
162
162
|
|
|
163
163
|
|
|
164
164
|
class Segment(Detect):
|
|
165
|
-
"""
|
|
165
|
+
"""YOLO Segment head for segmentation models."""
|
|
166
166
|
|
|
167
167
|
def __init__(self, nc=80, nm=32, npr=256, ch=()):
|
|
168
168
|
"""Initialize the YOLO model attributes such as the number of masks, prototypes, and the convolution layers."""
|
|
@@ -187,7 +187,7 @@ class Segment(Detect):
|
|
|
187
187
|
|
|
188
188
|
|
|
189
189
|
class OBB(Detect):
|
|
190
|
-
"""
|
|
190
|
+
"""YOLO OBB detection head for detection with rotation models."""
|
|
191
191
|
|
|
192
192
|
def __init__(self, nc=80, ne=1, ch=()):
|
|
193
193
|
"""Initialize OBB with number of classes `nc` and layer channels `ch`."""
|
|
@@ -217,7 +217,7 @@ class OBB(Detect):
|
|
|
217
217
|
|
|
218
218
|
|
|
219
219
|
class Pose(Detect):
|
|
220
|
-
"""
|
|
220
|
+
"""YOLO Pose head for keypoints models."""
|
|
221
221
|
|
|
222
222
|
def __init__(self, nc=80, kpt_shape=(17, 3), ch=()):
|
|
223
223
|
"""Initialize YOLO network with default parameters and Convolutional Layers."""
|
|
@@ -257,10 +257,10 @@ class Pose(Detect):
|
|
|
257
257
|
|
|
258
258
|
|
|
259
259
|
class Classify(nn.Module):
|
|
260
|
-
"""
|
|
260
|
+
"""YOLO classification head, i.e. x(b,c1,20,20) to x(b,c2)."""
|
|
261
261
|
|
|
262
262
|
def __init__(self, c1, c2, k=1, s=1, p=None, g=1):
|
|
263
|
-
"""Initializes
|
|
263
|
+
"""Initializes YOLO classification head to transform input tensor from (b,c1,20,20) to (b,c2) shape."""
|
|
264
264
|
super().__init__()
|
|
265
265
|
c_ = 1280 # efficientnet_b0 size
|
|
266
266
|
self.conv = Conv(c1, c_, k, s, p, g)
|
|
@@ -277,10 +277,10 @@ class Classify(nn.Module):
|
|
|
277
277
|
|
|
278
278
|
|
|
279
279
|
class WorldDetect(Detect):
|
|
280
|
-
"""Head for integrating
|
|
280
|
+
"""Head for integrating YOLO detection models with semantic understanding from text embeddings."""
|
|
281
281
|
|
|
282
282
|
def __init__(self, nc=80, embed=512, with_bn=False, ch=()):
|
|
283
|
-
"""Initialize
|
|
283
|
+
"""Initialize YOLO detection layer with nc classes and layer channels ch."""
|
|
284
284
|
super().__init__(nc, ch)
|
|
285
285
|
c3 = max(ch[0], min(self.nc, 100))
|
|
286
286
|
self.cv3 = nn.ModuleList(nn.Sequential(Conv(x, c3, 3), Conv(c3, c3, 3), nn.Conv2d(c3, embed, 1)) for x in ch)
|
ultralytics/utils/checks.py
CHANGED
|
@@ -238,12 +238,14 @@ def check_version(
|
|
|
238
238
|
c = parse_version(current) # '1.2.3' -> (1, 2, 3)
|
|
239
239
|
for r in required.strip(",").split(","):
|
|
240
240
|
op, version = re.match(r"([^0-9]*)([\d.]+)", r).groups() # split '>=22.04' -> ('>=', '22.04')
|
|
241
|
+
if not op:
|
|
242
|
+
op = ">=" # assume >= if no op passed
|
|
241
243
|
v = parse_version(version) # '1.2.3' -> (1, 2, 3)
|
|
242
244
|
if op == "==" and c != v:
|
|
243
245
|
result = False
|
|
244
246
|
elif op == "!=" and c == v:
|
|
245
247
|
result = False
|
|
246
|
-
elif op
|
|
248
|
+
elif op == ">=" and not (c >= v):
|
|
247
249
|
result = False
|
|
248
250
|
elif op == "<=" and not (c <= v):
|
|
249
251
|
result = False
|
|
@@ -333,18 +335,19 @@ def check_font(font="Arial.ttf"):
|
|
|
333
335
|
return file
|
|
334
336
|
|
|
335
337
|
|
|
336
|
-
def check_python(minimum: str = "3.8.0", hard: bool = True) -> bool:
|
|
338
|
+
def check_python(minimum: str = "3.8.0", hard: bool = True, verbose: bool = True) -> bool:
|
|
337
339
|
"""
|
|
338
340
|
Check current python version against the required minimum version.
|
|
339
341
|
|
|
340
342
|
Args:
|
|
341
343
|
minimum (str): Required minimum version of python.
|
|
342
344
|
hard (bool, optional): If True, raise an AssertionError if the requirement is not met.
|
|
345
|
+
verbose (bool, optional): If True, print warning message if requirement is not met.
|
|
343
346
|
|
|
344
347
|
Returns:
|
|
345
348
|
(bool): Whether the installed Python version meets the minimum constraints.
|
|
346
349
|
"""
|
|
347
|
-
return check_version(PYTHON_VERSION, minimum, name="Python", hard=hard)
|
|
350
|
+
return check_version(PYTHON_VERSION, minimum, name="Python", hard=hard, verbose=verbose)
|
|
348
351
|
|
|
349
352
|
|
|
350
353
|
@TryExcept()
|
|
@@ -374,8 +377,6 @@ def check_requirements(requirements=ROOT.parent / "requirements.txt", exclude=()
|
|
|
374
377
|
```
|
|
375
378
|
"""
|
|
376
379
|
prefix = colorstr("red", "bold", "requirements:")
|
|
377
|
-
check_python() # check python version
|
|
378
|
-
check_torchvision() # check torch-torchvision compatibility
|
|
379
380
|
if isinstance(requirements, Path): # requirements.txt file
|
|
380
381
|
file = requirements.resolve()
|
|
381
382
|
assert file.exists(), f"{prefix} {file} not found, check failed."
|
|
@@ -770,6 +771,8 @@ def cuda_is_available() -> bool:
|
|
|
770
771
|
return cuda_device_count() > 0
|
|
771
772
|
|
|
772
773
|
|
|
773
|
-
#
|
|
774
|
+
# Run checks and define constants
|
|
775
|
+
check_python("3.8", hard=False, verbose=True) # check python version
|
|
776
|
+
check_torchvision() # check torch-torchvision compatibility
|
|
774
777
|
IS_PYTHON_MINIMUM_3_10 = check_python("3.10", hard=False)
|
|
775
778
|
IS_PYTHON_3_12 = PYTHON_VERSION.startswith("3.12")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ultralytics
|
|
3
|
-
Version: 8.3.
|
|
3
|
+
Version: 8.3.10
|
|
4
4
|
Summary: Ultralytics YOLO for SOTA object detection, multi-object tracking, instance segmentation, pose estimation and image classification.
|
|
5
5
|
Author-email: Glenn Jocher <glenn.jocher@ultralytics.com>, Jing Qiu <jing.qiu@ultralytics.com>
|
|
6
6
|
Maintainer-email: Ultralytics <hello@ultralytics.com>
|
|
@@ -3,12 +3,11 @@ tests/conftest.py,sha256=9PFAiwAy6eeORGspr5dOKxVuFDVKqYg8Nn_RxSJ27UI,2919
|
|
|
3
3
|
tests/test_cli.py,sha256=E4lMt49TGo12Lb5CgQfpk1bwyFUZuFxF0V9j_ykV7xM,4821
|
|
4
4
|
tests/test_cuda.py,sha256=KoRtRLUB7KOb9IXYX4mCi295Uh_cZEEFhCyvCDGRK9s,5381
|
|
5
5
|
tests/test_engine.py,sha256=dcEcJsMQh61rDSNv7l4TIAgybLpzjVwerv9JZC_KCM8,4934
|
|
6
|
-
tests/test_explorer.py,sha256=9EeMtt4-K3-MeGnAc7NemTg3uTo-Xr6AYJlTJZJJeF8,2572
|
|
7
6
|
tests/test_exports.py,sha256=fpTKEVBUGLF3WiZPNKRs-IEcIY4cfxgvgKjUNfodjww,8042
|
|
8
7
|
tests/test_integrations.py,sha256=f5-QCUk1SU_-qn4mBCZwS3GN3tXEBIIXo4z2EhExbHw,6126
|
|
9
8
|
tests/test_python.py,sha256=I1RRdCwLdrc3jX06huVxct8HX8ccQOmQgVpuEflRl0U,23560
|
|
10
9
|
tests/test_solutions.py,sha256=dpxWGKO-aJ3Yff4KR7BQGajX9VyFdGTWEtcbmFC3WwE,3005
|
|
11
|
-
ultralytics/__init__.py,sha256=
|
|
10
|
+
ultralytics/__init__.py,sha256=r6LeW7qfMLanc7g2MYd3t48Oqt6LLDRB_PJFMVyyK3E,753
|
|
12
11
|
ultralytics/assets/bus.jpg,sha256=wCAZxJecGR63Od3ZRERe9Aja1Weayrb9Ug751DS_vGM,137419
|
|
13
12
|
ultralytics/assets/zidane.jpg,sha256=Ftc4aeMmen1O0A3o6GCDO9FlfBslLpTAw0gnetx7bts,50427
|
|
14
13
|
ultralytics/cfg/__init__.py,sha256=N-XONBXwmD3vzoE4icBXznkV8LOLmf6ak6mRdGPucvw,33146
|
|
@@ -96,9 +95,9 @@ ultralytics/data/base.py,sha256=ZCIhAyFfxXVp5fVnYD8mwbksNALJTayBKIR5FKGV7ZM,1516
|
|
|
96
95
|
ultralytics/data/build.py,sha256=AfMmz0sHIYmwry_90tEJFRk_kz0S3SolScVXqYHiT08,7261
|
|
97
96
|
ultralytics/data/converter.py,sha256=QCtrcbNz9kid8nvHfGIWt02nH1wwMKv6HI-8s927CR8,24251
|
|
98
97
|
ultralytics/data/dataset.py,sha256=D556AW0ZEsW3V8c5zJiHM_prc_YfZqymIkDKPw3k9Io,22936
|
|
99
|
-
ultralytics/data/loaders.py,sha256=
|
|
98
|
+
ultralytics/data/loaders.py,sha256=Fr70Q9p9t7buLW_8R2_lI_nyCMG033gWSxvwy1M-a-U,28449
|
|
100
99
|
ultralytics/data/split_dota.py,sha256=yOtypHoY5HvIVBKZgFXdfj2tuCLLEBnMwNfAeG94Eik,10680
|
|
101
|
-
ultralytics/data/utils.py,sha256=
|
|
100
|
+
ultralytics/data/utils.py,sha256=u6OZ7InLpI1em5aEPz13ZzS9BcO37dcY9_s2btXGZYQ,31076
|
|
102
101
|
ultralytics/data/explorer/__init__.py,sha256=-Y3m1ZedepOQUv_KW82zaGxvU_PSHcuwUTFqG9BhAr4,113
|
|
103
102
|
ultralytics/data/explorer/explorer.py,sha256=JWmLHHhp68h2q3vx4poBou5RYoAX3R89yihR50YLDb0,18881
|
|
104
103
|
ultralytics/data/explorer/utils.py,sha256=EvvukQiQUTBrsZznmMnyEX2EqTuwZo_Geyc8yfi8NIA,7085
|
|
@@ -107,7 +106,7 @@ ultralytics/data/explorer/gui/dash.py,sha256=6XOZy9NrkPEXREJPbi0EBkGgu78TAdHpdhS
|
|
|
107
106
|
ultralytics/engine/__init__.py,sha256=mHtJuK4hwF8cuV-VHDc7tp6u6D1gHz2Z7JI8grmQDTs,42
|
|
108
107
|
ultralytics/engine/exporter.py,sha256=DeHW_T_Zd3A21BLQYV1-FnS5EcmepMOy9nrussYNieU,57505
|
|
109
108
|
ultralytics/engine/model.py,sha256=Vtkza7cQrxvowb0PqGFhp7eC3cXRIKj6OUaR5d9w1-U,51464
|
|
110
|
-
ultralytics/engine/predictor.py,sha256=
|
|
109
|
+
ultralytics/engine/predictor.py,sha256=keTelEeo23Dcbs-XvmRWAPIs4pbCNDtsMBz88WM1eK8,17534
|
|
111
110
|
ultralytics/engine/results.py,sha256=8RJlN8J-_9w-mrDZm9wC-DZJTPBS7v1c_r_R173QyRM,75043
|
|
112
111
|
ultralytics/engine/trainer.py,sha256=6dGOEZvMo3o97SLpKlcR5XmhWhUHh05uLYpj3jNn0jU,36981
|
|
113
112
|
ultralytics/engine/tuner.py,sha256=gPqDTHH7vRB2O3YyH26m1BjVKbXxuA2XAlPRzTKFZsc,11838
|
|
@@ -181,7 +180,7 @@ ultralytics/nn/modules/__init__.py,sha256=xhW2BennT9U_VaMXVpRu-bdLgp1BXt9L8mkIUB
|
|
|
181
180
|
ultralytics/nn/modules/activation.py,sha256=chhn469wnRHEs5BMGNBYXwPYZc_7-urspTT8fnBd-xA,895
|
|
182
181
|
ultralytics/nn/modules/block.py,sha256=thcIPcnGRRxDDDswywJsfzbewr9XfTrzl_UvSl-bJ3c,41832
|
|
183
182
|
ultralytics/nn/modules/conv.py,sha256=vOeHZ6Z4sc6-9PrDmRGT1hFkxSBbbWkQm2jRbGGjpqQ,12705
|
|
184
|
-
ultralytics/nn/modules/head.py,sha256=
|
|
183
|
+
ultralytics/nn/modules/head.py,sha256=WnCpQDBlMDStpEs-m-R0vcKq28OX2FEgTcmHEpRL_pA,26609
|
|
185
184
|
ultralytics/nn/modules/transformer.py,sha256=tGiK8NmPfswwW1rbF21r5ILUkkZQ6Nk4s8j16vFBmps,18069
|
|
186
185
|
ultralytics/nn/modules/utils.py,sha256=a88cKl2wz1nMVSEBiajtvaCbDBQIkESWOKTZ_WAJy90,3195
|
|
187
186
|
ultralytics/solutions/__init__.py,sha256=6RDeXWO1QSaMgCq8YrWXaj2xvPw2sJwJL_a0dgjCvz0,648
|
|
@@ -207,7 +206,7 @@ ultralytics/trackers/utils/matching.py,sha256=3Ie1WNNRZ4_q3365F03XD7Nr9juZB_08mw
|
|
|
207
206
|
ultralytics/utils/__init__.py,sha256=du1Y1LMU0jQn_zWWnAIx9U8wn6Vh7ce-k7qMwi6y0po,48698
|
|
208
207
|
ultralytics/utils/autobatch.py,sha256=BO9MCRtrLDtrDQaxqV0BdjaYsgXf-q07Y3_VdGp4URY,4330
|
|
209
208
|
ultralytics/utils/benchmarks.py,sha256=8FYp5WPzcxcDaeg8ol2sgzRBHVGYatEO7f3MrmPF6nI,25097
|
|
210
|
-
ultralytics/utils/checks.py,sha256=
|
|
209
|
+
ultralytics/utils/checks.py,sha256=SsB3s1z9TtMjGelDkGZIi6B40VXmCtGw2hcOCyPikx4,29765
|
|
211
210
|
ultralytics/utils/dist.py,sha256=NDFga-uKxkBX2zLxFHSene_cCiGQJoyOeCXcN9JIOIk,2358
|
|
212
211
|
ultralytics/utils/downloads.py,sha256=o8RY9f0KrzWfueLs8DuJ5w8OWQ-ll4ZS9lX6MEFDi70,21977
|
|
213
212
|
ultralytics/utils/errors.py,sha256=GqP_Jgj_n0paxn8OMhn3DTCgoNkB2WjUcUaqs-M6SQk,816
|
|
@@ -233,9 +232,9 @@ ultralytics/utils/callbacks/neptune.py,sha256=IbGQfEltamUKXJt93uSLQFn8c2rYh3DMTg
|
|
|
233
232
|
ultralytics/utils/callbacks/raytune.py,sha256=ODVYzy-CoM4Uge0zjkh3Hnh9nF2M0vhDrSenXnvcizw,705
|
|
234
233
|
ultralytics/utils/callbacks/tensorboard.py,sha256=bv4fkkesdgmZv_E2MU6wuaMBwEV5iI2G53RHPyD9quw,4170
|
|
235
234
|
ultralytics/utils/callbacks/wb.py,sha256=upfbF8-LLXueUvulLaMDmKDhKCl_PWbNa_87PQ0L0Rc,6752
|
|
236
|
-
ultralytics-8.3.
|
|
237
|
-
ultralytics-8.3.
|
|
238
|
-
ultralytics-8.3.
|
|
239
|
-
ultralytics-8.3.
|
|
240
|
-
ultralytics-8.3.
|
|
241
|
-
ultralytics-8.3.
|
|
235
|
+
ultralytics-8.3.10.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
|
236
|
+
ultralytics-8.3.10.dist-info/METADATA,sha256=erZGLlFck6gorIKxGLLR-ymgpHCb5WiGGa89PyM_sQs,34700
|
|
237
|
+
ultralytics-8.3.10.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
238
|
+
ultralytics-8.3.10.dist-info/entry_points.txt,sha256=YM_wiKyTe9yRrsEfqvYolNO5ngwfoL4-NwgKzc8_7sI,93
|
|
239
|
+
ultralytics-8.3.10.dist-info/top_level.txt,sha256=XP49TwiMw4QGsvTLSYiJhz1xF_k7ev5mQ8jJXaXi45Q,12
|
|
240
|
+
ultralytics-8.3.10.dist-info/RECORD,,
|
tests/test_explorer.py
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
|
2
|
-
|
|
3
|
-
import PIL
|
|
4
|
-
import pytest
|
|
5
|
-
|
|
6
|
-
from ultralytics import Explorer
|
|
7
|
-
from ultralytics.utils import ASSETS
|
|
8
|
-
from ultralytics.utils.torch_utils import TORCH_1_13
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@pytest.mark.slow
|
|
12
|
-
@pytest.mark.skipif(not TORCH_1_13, reason="Explorer requires torch>=1.13")
|
|
13
|
-
def test_similarity():
|
|
14
|
-
"""Test the correctness and response length of similarity calculations and SQL queries in the Explorer."""
|
|
15
|
-
exp = Explorer(data="coco8.yaml")
|
|
16
|
-
exp.create_embeddings_table()
|
|
17
|
-
similar = exp.get_similar(idx=1)
|
|
18
|
-
assert len(similar) == 4
|
|
19
|
-
similar = exp.get_similar(img=ASSETS / "bus.jpg")
|
|
20
|
-
assert len(similar) == 4
|
|
21
|
-
similar = exp.get_similar(idx=[1, 2], limit=2)
|
|
22
|
-
assert len(similar) == 2
|
|
23
|
-
sim_idx = exp.similarity_index()
|
|
24
|
-
assert len(sim_idx) == 4
|
|
25
|
-
sql = exp.sql_query("WHERE labels LIKE '%zebra%'")
|
|
26
|
-
assert len(sql) == 1
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@pytest.mark.slow
|
|
30
|
-
@pytest.mark.skipif(not TORCH_1_13, reason="Explorer requires torch>=1.13")
|
|
31
|
-
def test_det():
|
|
32
|
-
"""Test detection functionalities and verify embedding table includes bounding boxes."""
|
|
33
|
-
exp = Explorer(data="coco8.yaml", model="yolo11n.pt")
|
|
34
|
-
exp.create_embeddings_table(force=True)
|
|
35
|
-
assert len(exp.table.head()["bboxes"]) > 0
|
|
36
|
-
similar = exp.get_similar(idx=[1, 2], limit=10)
|
|
37
|
-
assert len(similar) > 0
|
|
38
|
-
# This is a loose test, just checks errors not correctness
|
|
39
|
-
similar = exp.plot_similar(idx=[1, 2], limit=10)
|
|
40
|
-
assert isinstance(similar, PIL.Image.Image)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
@pytest.mark.slow
|
|
44
|
-
@pytest.mark.skipif(not TORCH_1_13, reason="Explorer requires torch>=1.13")
|
|
45
|
-
def test_seg():
|
|
46
|
-
"""Test segmentation functionalities and ensure the embedding table includes segmentation masks."""
|
|
47
|
-
exp = Explorer(data="coco8-seg.yaml", model="yolo11n-seg.pt")
|
|
48
|
-
exp.create_embeddings_table(force=True)
|
|
49
|
-
assert len(exp.table.head()["masks"]) > 0
|
|
50
|
-
similar = exp.get_similar(idx=[1, 2], limit=10)
|
|
51
|
-
assert len(similar) > 0
|
|
52
|
-
similar = exp.plot_similar(idx=[1, 2], limit=10)
|
|
53
|
-
assert isinstance(similar, PIL.Image.Image)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
@pytest.mark.slow
|
|
57
|
-
@pytest.mark.skipif(not TORCH_1_13, reason="Explorer requires torch>=1.13")
|
|
58
|
-
def test_pose():
|
|
59
|
-
"""Test pose estimation functionality and verify the embedding table includes keypoints."""
|
|
60
|
-
exp = Explorer(data="coco8-pose.yaml", model="yolo11n-pose.pt")
|
|
61
|
-
exp.create_embeddings_table(force=True)
|
|
62
|
-
assert len(exp.table.head()["keypoints"]) > 0
|
|
63
|
-
similar = exp.get_similar(idx=[1, 2], limit=10)
|
|
64
|
-
assert len(similar) > 0
|
|
65
|
-
similar = exp.plot_similar(idx=[1, 2], limit=10)
|
|
66
|
-
assert isinstance(similar, PIL.Image.Image)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|