Джерела передбачення
Аргумент source класифікується до відкриття будь-яких даних, тому один виклик обробляє JPEG, папку, MP4, індекс вебкамери, URL RTSP, область екрана або список камер.
Класифікація джерела
classify_source перевіряє значення до відкриття чи завантаження будь-яких
даних у наведеному порядку. Застосовується перше правило, що збігається.
| Джерело | Інтерпретація |
|---|---|
"screen", "screen 1", "screen 1 100 200 512 256" | Захоплення екрана |
Невід'ємне int або рядок із цифр, якщо файла з такою назвою немає | Вебкамера |
URL rtsp://, rtmp://, tcp:// або udp:// | Мережевий потік |
URL http(s)://, шлях якого закінчується на .m3u8 | Мережевий потік |
| URL сторінки YouTube | Мережевий потік |
| Список або кортеж, усі елементи якого є джерелами наживо чи відео | Кілька потоків наживо |
| Будь-який інший список або кортеж | Батч зображень |
Шлях, що закінчується на .streams | Кілька потоків наживо |
| Шлях із розширенням відео | Відеофайл |
| Наявний каталог | Папка зображень |
| Усе інше | Одне зображення |
Список, у якому джерела наживо змішано із зображеннями, спричиняє TypeError.
Від'ємний індекс вебкамери спричиняє ValueError.
Класифікатор ніколи не звертається до мережі, тому помилка в URL проявляється
під час відкриття захоплення, а не під час виклику predict.
Зображення
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreYOLO9s.pt") # Джерело з одним зображенням повертає один Results, а не список.result = model(SAMPLE_IMAGE)print(len(result.boxes), "detections")import numpy as npfrom PIL import Image from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreYOLO9s.pt") pil_image = Image.open(SAMPLE_IMAGE)array = np.asarray(pil_image)raw_bytes = open(SAMPLE_IMAGE, "rb").read() # Масиви NumPy зчитуються як BGR, якщо не вказано інше; цей масив у RGB.result = model(array, color_format="rgb")print(type(array).__name__, len(result.boxes)) for source in (pil_image, raw_bytes): result = model(source) print(type(source).__name__, len(result.boxes))from pathlib import Pathfrom PIL import Image from libreyolo import LibreYOLO, SAMPLE_IMAGE folder = Path("sample_folder")folder.mkdir(exist_ok=True)image = Image.open(SAMPLE_IMAGE)for index in range(3): image.save(folder / f"frame_{index}.jpg") model = LibreYOLO("LibreYOLO9s.pt") # Папка повертає список з одним Results на зображення, відсортований за шляхом.results = model(str(folder))print(len(results), "images")libreyolo predict model=LibreYOLO9s.pt \ source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpgДжерело з одним зображенням приймає сім типів.
| Тип | Інтерпретація |
|---|---|
str або pathlib.Path | Локальний файл, http(s)://, s3:// або gs:// |
PIL.Image.Image | Перетворюється на RGB |
numpy.ndarray | 2D у відтінках сірого або 3D HWC чи CHW у порядку BGR; 4D масив є батчем |
torch.Tensor | CHW або NCHW, зчитується як RGB; 4D тензор є батчем |
bytes | Закодовані дані зображення |
io.BytesIO | Закодовані дані зображення |
4D масив або тензор повертає список з одним Results на зображення.
До попереднього оброблення все перетворюється на RGB. Порядок каналів
неоднозначний лише для масивів NumPy, тому ним керує color_format: "auto"
(типове значення) і "bgr" зчитують масив як BGR, у порядку, який повертає
OpenCV, а "rgb" залишає масив без змін, що потрібно для масиву, створеного із
зображення PIL.
Масиви з рухомою комою масштабуються за власним діапазоном: значення не вище
1.0 множаться на 255, а вищі значення обмежуються діапазоном [0, 255].
У масиві RGBA альфа-канал відкидається.
Для кожного типу віддалених шляхів потрібен окремий пакет. requests для
http(s):// входить до базового встановлення; boto3 для s3:// і gcsfs для
gs:// не входять.
Відстеження приймає зображення, каталоги з сортуванням за назвами файлів, списки, кортежі й ліниві ітератори зображень як послідовні кадри. Передайте fps=30.0, щоб задати часову шкалу послідовності, і color_format="auto", щоб вибрати інтерпретацію вхідних даних. Див. відстеження.
Папки
Каталог сканується рекурсивно й сортується, а кожен файл з одним із наведених
суфіксів стає зображенням: .jpg, .jpeg, .png, .gif, .webp, .bmp,
.tiff, .tif. Усе інше в папці пропускається. Порожня папка повертає порожній
список, а не спричиняє помилку.
Папки та списки є двома джерелами, які приймають batch. Для сімейств із
підтримкою ця функція виконує один прямий прохід складеного тензора на групу.
Дивіться Продуктивність інференсу.
Відеофайли
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # Замініть clip.mp4 на відеофайл із диска.for result in model("clip.mp4", stream=True): print(result.frame_idx, len(result.boxes))from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") for result in model("clip.mp4", stream=True, vid_stride=3, save=True): passШлях вважається відео, якщо його суфікс є одним із таких: .3g2, .3gp,
.asf, .avi, .dav, .f4v, .flv, .gif, .h264, .h265, .hevc,
.m2ts, .m4v, .mkv, .mov, .mp4, .mpeg, .mpg, .mts, .mxf, .ogv,
.ts, .vob, .wmv, .webm.
.gif є в обох списках. Шлях .gif, переданий безпосередньо до predict,
відкривається як відео, оскільки перевірка відео виконується першою; файл .gif
усередині сканованої папки завантажується як нерухоме зображення.
vid_stride обробляє кожен N-й кадр і типово дорівнює 1. Без stream=True
усе відео декодується в список, а понад 500 кадрів після застосування кроку
спричиняють попередження з рекомендацією stream=True.
Кожен Results із відео містить frame_idx.
Якщо H.264 не відкривається, кодування відео переходить до доступного кодека. Резервний варіант записується в журнал на рівні INFO й кешується для кожної пари кодека та полотна лише після успішного використання іншого кодека.
Вебкамери, мережеві потоки та YouTube
import itertools from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # Індекс вебкамери 0. Джерела наживо нескінченні, тому обмежте цикл.for result in itertools.islice(model(0, stream=True), 100): print(result.frame_idx, len(result.boxes))import itertools from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")source = "rtsp://user:password@192.168.1.64:554/Streaming/Channels/101" for result in itertools.islice(model(source, stream=True), 100): print(result.frame_idx, len(result.boxes))Джерела наживо необмежені, тому потребують stream=True. Без нього predict
спричиняє ValueError, а не намагається зібрати нескінченний список.
Кадри зчитуються у фоновому потоці, по одному на кожне захоплення. Типово черга
зберігає лише найновіший кадр, тому модель, повільніша за камеру, пропускає кадри,
а не відстає. stream_buffer=True зберігає кожен захоплений кадр, що не втрачає
їх ціною дедалі більшої затримки.
Індекс вебкамери задається як int або рядок із цифр. У Windows захоплення
спочатку відкривається через бекенд DirectShow, а в разі невдачі переходить до
типового бекенда.
URL сторінки YouTube перетворюється на прямий URL медіаданих без завантаження
відео, для чого потрібен yt-dlp:
pip install "libreyolo[stream]"Мітки потоків редагуються перед записом у журнал або використанням як назв
файлів. URL з обліковими даними відображається як user:***@host, а рядки
запиту вилучаються з міток прямих потоків, оскільки там розташовуються підписані
URL і токени пред'явника. Ідентифікатор відео YouTube зберігається, бо він не є
обліковими даними.
Кілька камер одночасно
import itertoolsfrom pathlib import Path from libreyolo import LibreYOLO Path("cameras.streams").write_text( "# one source per line, blank lines and comments are skipped\n" "rtsp://192.168.1.64:554/Streaming/Channels/101\n" "rtsp://192.168.1.65:554/Streaming/Channels/101\n", encoding="utf-8",) model = LibreYOLO("LibreYOLO9s.pt")for result in itertools.islice(model("cameras.streams", stream=True), 100): print(result.frame_idx, len(result.boxes))import itertools from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")cameras = [0, "rtsp://192.168.1.64:554/Streaming/Channels/101"] for result in itertools.islice(model(cameras, stream=True), 100): print(result.frame_idx, len(result.boxes))Файл .streams містить одне джерело на рядок. Порожні рядки й рядки, що
починаються з #, ігноруються. Кожен інший рядок має містити індекс вебкамери,
мережевий потік, URL YouTube або шлях до відеофайла; усе інше спричиняє
ValueError із номером рядка. Порожній файл спричиняє помилку, а не запускає
оброблення без камер.
Список або кортеж джерел наживо дає той самий результат без файла.
Кожне захоплення отримує власний потік, а кадри з усіх них мультиплексуються в один генератор. Кожен прохід опитує всі активні потоки й повертає готові дані, тому повільна камера не затримує швидку, а кадри з різних камер чергуються. Потік, що завершився, вилучається з ротації, а решта продовжує працювати.
Захоплення екрана
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # Без stream=True отримується один кадр.result = model("screen")print(len(result.boxes), "detections")import itertools from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # "screen <monitor> <left> <top> <width> <height>"for result in itertools.islice(model("screen 1 100 200 512 256", stream=True), 50): print(len(result.boxes))Джерело екрана задається словом screen, після якого йде нуль, одне, чотири
або п'ять цілих чисел. Будь-яка інша кількість спричиняє ValueError.
| Форма | Захоплює |
|---|---|
"screen" | Усі монітори разом |
"screen 1" | Монітор 1 |
"screen 100 200 512 256" | Прямокутник на об'єднаному робочому столі |
"screen 1 100 200 512 256" | Прямокутник на моніторі 1 |
Координати прямокутника задано як left top width height відносно верхнього
лівого кута вибраного монітора. Джерело екрана повідомляє частоту кадрів як 30,
поділене на vid_stride; з такою частотою записується збережене відео. Для
захоплення потрібен пакет mss:
pip install mssБез stream=True джерело екрана захоплює один кадр і повертає один Results,
що відповідає передбаченню для знімка екрана як файла зображення. Зі
stream=True захоплення триває до переривання циклу.
Що повертає predict
Форма поверненого значення залежить від джерела та stream.
| Джерело | stream=False | stream=True |
|---|---|---|
| Одне зображення | Один Results | Генератор одного Results |
| Список зображень | Список Results | Генератор |
| Папка | Список Results | Генератор |
| Відеофайл | Список Results | Генератор |
| Екран | Один Results | Необмежений генератор |
Вебкамера, мережевий потік, .streams | ValueError | Необмежений генератор |
Одне зображення повертає сам об'єкт Results. Індексування вибирає в ньому
виявлення, а не зображення, тому result[0] для передбачення одного зображення
є першою рамкою, а не першою картинкою. Вміст цих об'єктів описано в розділі
Робота з результатами.
Куди записує save
save=True записує анотований вивід у каталог запуску, а не повертає його.
Зображення потрапляють до автоматично нумерованих каталогів
runs/detect/predict, runs/detect/predict2 тощо зі збереженням назви файла
джерела. Усі зображення одного процесу потрапляють до одного каталогу, тому дві
вхідні папки з однаковою назвою файла перезаписують одна одну. Зображення з
пам'яті не мають назви файла для повторного використання. Одне таке зображення
зберігається як inference, тому повторні виклики його перезаписують; список
або батч нумерується як image0, image1 тощо. Два процеси, що зберігають
одночасно, отримують окремі пронумеровані каталоги, бо кожен запуск резервує
свій каталог, створюючи його.
Відео та джерела наживо записуються як один файл .mp4, названий за джерелом.
output_path перевизначає каталог. Шлях із суфіксом розглядається як файл, а
шлях без нього як каталог. output_file_format вибирає кодування нерухомого
зображення та приймає jpg, png або webp.
Після збереження зображення записаний шлях також додається до результату як result.saved_path.