Ultralytics YOLO27: Встать в лист ожидания.
Get Started
Урокначинающий

Собирай качественные и репрезентативные данные

Бери изображения из реальных условий внедрения, указывай метаданные съёмки в каждом имени файла, отслеживай покрытие по спецификации и выбирай кадры из видео так, чтобы не перегружать датасет.

Большинство проблем с датасетами связано со сбором данных. Команда снимает чистые примеры одной камерой за одну неделю, проверка показывает отличные результаты, а на втором объекте модель работает из рук вон плохо. Сбор данных задаёт верхнюю планку: ни качество разметки, ни аугментация, ни гиперпараметры не научат модель работать в сцене, которой не было в датасете.

Результат

Создай датасет, в именах файлов которого указаны камера, день и кадр; оцени его покрытие относительно квот спецификации и сократи число кадров из видео, оставив только разные сцены.

Ускоренное прохождение
Если ты уже освоился, вот краткая версия.
  1. Снимай на производственные камеры, на которых будет работать модель.

  2. Называй каждый файл camera_day_frame, чтобы на следующих этапах можно было группировать данные и проверять их.

  3. Сравнивай число изображений с каждой камеры, за каждый день и для каждого сценария с требованиями спецификации и собирай недостающие данные.

  4. Отбирай из видео только кадры, на которых сцена изменилась.

  5. Используй общедоступные, постановочные или синтетические изображения только для заполнения обозначенных пробелов.

Практические занятия

Разнообразие важнее объёма#

Сравним два датасета, предназначенных для одного и того же внедрения:

ДатасетРезультат проверкиВ производственной среде
10 000 почти одинаковых кадров, одна камера, только полденьВысокий: кадры val похожи на кадры trainРезультаты хуже при съёмке другой камерой и в сумерках
1 500 кадров, распределённых по 12 сценариям из спецификацииСкромнееРаботает стабильно, потому что производственные условия похожи на данные

Высокая оценка проверки первого датасета объясняется тем, что проверка охватывает только одно представленное в нём условие. В производственной среде качество модели определяется тем сценарием, который представлен хуже всего. В первую очередь собирай данные так, чтобы охватить спецификацию, и лишь затем увеличивай их объём.

Выбирай источники в правильном порядке#

Большая часть датасета должна поступать из реальных производственных условий. В руководстве по сбору и аннотированию данных каждый источник описан подробнее:

ИсточникКогда полезенКогда вредит
Текущие данные с производственных камерМаксимально соответствуют условиям внедренияСобирать медленно; могут потребоваться соглашения на обработку данных
Архивные данные с производственных камерПозволяют быстро получить большое разнообразиеСтарые записи могут не соответствовать текущим условиям
Общедоступные датасеты (COCO, Open Images, VOC)Первичное обучение на распространённых классахСдвиг домена относительно твоих сцен
Постановочная съёмкаСбор конкретных граничных случаев по запросуСлишком чистые данные; легко начать чрезмерно на них полагаться
Синтетические или сгенерированные изображенияРедкие опасные ситуации и неисправности, которых нельзя ждатьМодель может перенять стиль генератора
Сбор изображений из интернетаРазнообразие с низкими затратамиНестабильное качество и риск нарушения лицензий

Используй постановочные, общедоступные и синтетические изображения для заполнения конкретных пробелов, указанных в спецификации, и отслеживай их долю в датасете, чтобы оценить их пользу. На платформе Ultralytics функция Generate similar images добавляет в датасет сгенерированные вариации существующего изображения — без разметки, готовые к аннотированию.

Указывай метаданные в имени файла#

Для каждого изображения нужны как минимум ID камеры, день съёмки и номер кадра или клипа. Без них позже ты не сможешь разделить данные по группам, отследить источник регрессии или собрать дополнительные данные для недостаточно представленного сценария. Самый надёжный способ хранения этих данных — имя файла: cam2_2026-05-01_000124.jpg сохраняется при работе в любых инструментах, экспорте и загрузке. Поиск в датасетах платформы Ultralytics выполняется по именам файлов и пользовательским метаданным, поэтому после загрузки эти ключи останутся доступными для поиска.

Этот скрипт создаёт учебный датасет, который используется в остальной части курса. Он копирует размеченные изображения COCO128 и переименовывает их так, будто четыре камеры снимали в течение четырёх дней; при этом данные камеры cam1 представлены с избытком, как это часто бывает с удобной для съёмки камерой:

import shutil
from pathlib import Path

from ultralytics.data.utils import check_det_dataset, img2label_paths

data = check_det_dataset("coco128.yaml")  # 128 COCO images stand in for your camera captures
out = Path("datasets/practice")
(out / "images").mkdir(parents=True, exist_ok=True)
(out / "labels").mkdir(parents=True, exist_ok=True)

for i, image in enumerate(sorted(Path(data["train"]).glob("*.jpg"))):
    camera = ("cam1", "cam1", "cam2", "cam3", "cam4")[i % 5]  # cam1 over-collected, like a real site
    name = f"{camera}_2026-05-0{i // 32 + 1}_{i:06d}"  # camera, capture day, frame number
    shutil.copy(image, out / "images" / f"{name}.jpg")
    label = Path(img2label_paths([str(image)])[0])
    if label.exists():
        shutil.copy(label, out / "labels" / f"{name}.txt")

print(len(list((out / "images").glob("*.jpg"))), "images written to", out)
128 images written to datasets/practice

Диалог создания датасета на платформе Ultralytics: добавь изображения, видео или датасеты в форматах YOLO, COCO или NDJSON, затем укажи название датасета, URL, описание, тип задачи, лицензию, размытие лиц и видимость

При загрузке на платформу Ultralytics имена файлов сохраняются. В диалоге загрузки также можно добавить видео и целые датасеты, а среди настроек есть размытие лиц для защиты конфиденциальности.

Отслеживай покрытие по спецификации#

Если метаданные указаны в именах файлов, покрытие можно посчитать. Задай квоты по спецификации, и скрипт подскажет, что собирать дальше:

from collections import Counter
from pathlib import Path

QUOTA = {"cam1": 30, "cam2": 30, "cam3": 30, "cam4": 30}  # images per camera, from your spec

images = sorted(Path("datasets/practice/images").glob("*.jpg"))
cameras = Counter(p.stem.split("_")[0] for p in images)
days = Counter(p.stem.split("_")[1] for p in images)

for camera, quota in QUOTA.items():
    gap = quota - cameras[camera]
    print(f"{camera}: {cameras[camera]:3d} / {quota}  {'ok' if gap <= 0 else f'collect {gap} more'}")
print("days:", dict(sorted(days.items())))
cam1:  52 / 30  ok
cam2:  26 / 30  collect 4 more
cam3:  25 / 30  collect 5 more
cam4:  25 / 30  collect 5 more
days: {'2026-05-01': 32, '2026-05-02': 32, '2026-05-03': 32, '2026-05-04': 32}

Правило принятия решения: прекрати сбор из любого источника, где квота уже превышена, и сосредоточь усилия на пробелах. Здесь на cam1 уже приходится 40% изображений. Ещё одна неделя съёмки этой камерой увеличит объём, но не улучшит покрытие.

Отбирай кадры из видео, не перегружая датасет#

Видео — самый дешёвый источник данных и источник, который проще всего использовать неправильно. При 30 кадрах в секунду за минуту получается 1 800 почти одинаковых кадров, а повторная разметка одного и того же момента стоит денег и завышает метрики. Оставляй кадр, только если сцена изменилась по сравнению с последним сохранённым кадром:

from pathlib import Path

import cv2

from ultralytics.utils.downloads import safe_download

video = "solutions_ci_demo.mp4"  # a short public demo clip; swap in your own footage
safe_download(f"https://github.com/ultralytics/assets/releases/download/v0.0.0/{video}")
Path("frames").mkdir(exist_ok=True)

cap = cv2.VideoCapture(video)
fps = cap.get(cv2.CAP_PROP_FPS)
read = kept = 0
last = None
while True:
    ok, frame = cap.read()
    if not ok:
        break
    thumb = cv2.cvtColor(cv2.resize(frame, (64, 64)), cv2.COLOR_BGR2GRAY).astype(float)
    if last is None or abs(thumb - last).mean() > 10:  # keep a frame only when the scene has changed
        cv2.imwrite(f"frames/clip01_{read:06d}.jpg", frame)  # the clip ID stays in the filename
        kept, last = kept + 1, thumb
    read += 1

print(f"{read} frames at {fps:.0f} FPS -> {kept} kept")
62 frames at 30 FPS -> 6 kept

В двухсекундном клипе 62 кадра, но лишь 6 визуально различающихся моментов. Скрипт сравнивает крошечные изображения в оттенках серого, поэтому быстро обрабатывает даже многочасовые записи. Увеличь порог 10, чтобы сохранять меньше кадров со статичных камер; уменьши его для быстро меняющихся сцен. Распределяй бюджет и между клипами: 20 кадров из каждого из 50 клипов лучше, чем 1 000 кадров из одного.

Кадры из одного видео — это один пример, а не множество

Два кадра с интервалом в секунду имеют одинаковое освещение и фон и обычно содержат те же объекты. Если они попадут и в обучающую, и в валидационную выборку, модель будет оцениваться на изображениях, которые фактически уже видела. Указывай ID видео в каждом имени файла, чтобы разделить набор данных правильно и не разрывать видео.

Избегай ошибок при сборе данных#

ОшибкаСимптомРешение
Сбор данных в течение одной неделиВысокий mAP на валидации, но ошибки в другие сезоны или при смене условийРаспредели сбор данных на несколько недель или месяцев
Одна камераМодель не работает со второй камеройСобирай данные со всех типов камер, которые используешь
Только постановочные данныеМодель не справляется с реальным беспорядкомОставь постановочные изображения небольшой отслеживаемой долей данных
Дублирующиеся кадрыЗавышенные метрики и напрасная разметкаОтбирай данные по смене сцены; Ultralytics Platform также пропускает точные копии при загрузке
Один оператор или сменаНезапланированное разнообразие внешнего вида и дисбаланс классовСобирай данные в разные смены, на разных объектах и с разными людьми
Недостаточно редких случаевМодель пропускает самые важные события, связанные с безопасностьюЦелевой сбор данных, постановка сцен или дополнение синтетическими данными

Смещение — это проблема сбора данных, а не моделирования: никакой гиперпараметр не исправит отсутствие в данных целой группы. В руководстве по сбору данных перечислены четыре способа решения: разнообразные источники, сбалансированное представление, регулярная повторная проверка охвата и меры по снижению смещения, например увеличение выборки недостаточно представленных групп.

Если на изображениях есть лица, номерные знаки или другие персональные данные, до начала сбора данных нужно получить согласие и определить политику хранения. С глоссария по теме конфиденциальности данных удобно начать, а в разделе «Конфиденциальность, регионы и соответствие требованиям» описано, как хранить данные в нужной юрисдикции с помощью dataRegion.

Попробовать

Запусти make_practice_set.py, затем измени квоты в coverage.py в соответствии со своей спецификацией (или оставь учебные квоты) и запусти его. Для реального проекта переименуй 50 недавних изображений по шаблону camera_day_frame и подсчитай по ним охват тем же способом. Результат: отчет об охвате и план сбора данных, в котором перечислены все источники с превышенной квотой и все пробелы с указанием их размера.

Критерии готовности
Урок считается завершённым, если выполнены все условия ниже.
  • В имени файла каждого изображения указаны камера (или источник), день съемки и номер кадра или клипа.

  • В отчете об охвате количество изображений по каждой камере, дню или сценарию сравнивается с квотами спецификации.

  • Видео обрабатывается с выборкой по смене сцены, а у сохраненных кадров остается идентификатор клипа.

Показать решение

Для учебного набора отчет об охвате дает четкий план:

ИсточникКоличество / квотаДействие
cam152 / 30Прекрати сбор: здесь уже 40% всех изображений
cam226 / 30Собери еще 4
cam325 / 30Собери еще 5
cam425 / 30Собери еще 5

Каждая камера охватывает все четыре дня, поэтому пробелы относятся к камерам, а не к дням. Распредели 14 новых изображений как минимум по двум новым дням, чтобы добавить новые условия, а не еще больше материалов за тот же день. Если для камеры невозможно восполнить пробел (например, она снимает только ночью), добавь в спецификацию строку для недостающего условия и зафиксируй, будут ли его покрывать постановочные или сгенерированные изображения, чтобы позже можно было оценить их влияние.

Что дальше

После сбора изображений в следующем уроке ты научишься сразу размечать их единообразно.

Войди, чтобы сохранять прогресс