Задача обнаружения объектов на изображении не нова, подходов к её решению существует масса. Вероятно, самым популярным и известным среди них будет YOLO. Появившись в 2015 году, эта серия систем по сей день используется, когда хочется сделать детекцию быстро, без долгих экспериментов с архитектурой.
Небольшая историческая справка. Название “YOLO” (You Only Look Once) отлично передаёт суть подхода. Старые детекторы вроде R-CNN работали в 2 прохода: смотрели, где на картинке в принципе что-то есть, после чего выполняли классификацию, каждого куска. Надёжно, но очень медленно. YOLO же смотрит на изображение один раз. Делит его сеткой и сразу для каждой ячейки предсказывает рамку. Это даёт высокую скорость, благодаря чему YOLO всё ещё остаётся актуальным, применяется, если необходим быстрый отклик (видеопоток в реальном времени) или при ограниченных ресурсах.
Однако, какой бы ни была архитектура, всё их объединяет одна и та же проблема — данные. Для полноценного обучения нужны сотни и тысячи изображений, с разных ракурсов, в разных условиях. Если цель — академический проект, обнаружение машин или колосков пшеницы, то найти датасет не составляет проблем. Но что, если датасета нет и/или его невозможно собрать в принципе в нужном объёме? Скажем, редкий дефект в производстве, истребитель новой конструкции? Ждать, пока накопится много брака, или надеяться на утечку чертежей?
Мы провели пару экспериментов с моделью YOLO для проверки гипотезы: как далеко можно зайти, используя исключительно синтетические данные?
Одуванчики: начало
Решили начать с простого, что можно относительно легко проверить — поиск жёлтых одуванчиков. Обучали модель не на реальных снимках с лугов, а на сгенерированных изображениях цветов.
Синтетику использовали и раньше, делали рендеры в Blender или Unity, буквально рисовали объекты вручную, после чего расставляли их, меняли освещение, ракурсы. Но, во-первых, что очевидно, это очень медленно. Каждая сцена, по сути, собирается руками, каждый объект внутри неё. Сделать быстро — картинка получится «пластиковой», непригодной для обучения. Сделать качественно — значит потратить очень много времени.
Ранние генеративные модели выдавали очень плохие результаты. Ни о какой фотореалистичности речи не шло. Успехом было, что картинка была в принципе приблизительно похожей на то, что требовалось. Для обучения это ещё хуже «пластика» от рендеров, модель выучит не объект, а кривую галлюцинацию.
И только сейчас качество генерации дошло до того уровня, когда синтетика на глаз неотличима от реального фото. Значит, уже можно попытаться. Старались над генерацией датасета последние, на момент написания статьи, Gemini 3 Pro, Gemini 3.1 Flash, GPT Image 2 и немного добавляли разнообразия Grok с Qwen’ом на пару.
Возникает вопрос: «для чего такой зоопарк из моделей?» Нет, не от жадности или просто «чтобы было». Причин на это две.
Во-первых, это аугментация ещё до всякой аугментации. В обычном понимании аугментация — это постобработка: поворот картинки, изменение цветов, размытие и т. п. В контексте нейросетей смысл немного меняется. У каждой модели есть свой «почерк», при одном и том же промпте результаты будут отличаться почти всегда, в значительной степени.
Во-вторых, что ещё намного важнее — невидимые маркеры. И Gemini, и GPT помещают в изображение специальные метки.

На глаз их не видно, но модели, склонные искать простые пути решения, с радостью переобучатся именно на таких артефактах. Поэтому кормить YOLO изображениями только одной модели — значит обучать её понимать геометрию объекта «через линзу вотермарки». Это и создаёт domain gap. На синтетике метрики будут отличные, но в реальности, увидев объект «без фильтра», модель растеряется. Намешав источники, мы делаем маркер менее значимым признаком.
Пайплайн создания датасета выглядит следующим образом:
-
Генерация. Причём генерация не только изображений, но и промптов для генерации этих изображений (если делать синтетику, то end-to-end).
-
Разметка. Вот здесь уже пришлось поработать руками. Загрузили все картинки в Roboflow, обвели рамками, разбили на train/set/val и сразу сделали аугментацию, чтобы снизить влияние артефактов генерации.
-
Экспорт. Все изображения были упакованы в zip и выгружены для локального обучения модели.
Итого получилось 248 изображений на обучение, плюс небольшие валидационная и тестовая выборки. Один класс: yellow_dandelion. Все изображения в 640×640.
Одуванчики: результат
Взяли простую и очень лёгкую версию: YOLOv8 — максимально приближено к потенциальному сценарию применения, о котором будет сказано далее. Модель обучилась быстро и по итогу имеем:
|
mAP@50 |
83.9% |
|
Precision |
92.2% |
|
Recall |
74.6% |
|
F1 |
82.5% |
Любой детектор не просто говорит «здесь объект», но и обводит его рамкой. Чтобы понять, угадал он или нет, рамку модели сравнивают с эталонной разметкой через метрику IoU — насколько сильно два прямоугольника перекрываются. Перекрытие больше 50% — засчитываем попадание, меньше — мимо. Отсюда и название mAP@50: это усреднённая точность детекции при пороге IoU в 0.5. Наши 83.9% говорят, что модель в большинстве случаев не просто находит цветок, но и обводит его достаточно метко.
92% на Precision значит, что модель почти не ошибается: если сказано «одуванчик», значит, это действительно одуванчик, а не кусок жёлтой обёртки. Recall чуть ниже — 74.6% — иногда модель сомневается и пропускает цветок. То есть она предпочитает промолчать, чем выдать ложное срабатывание.
F1, по своей сути, агрегат из Precision и Recall, способ свести их в одно число. Если быть точнее, это их гармоническое среднее. Нового знания не добавляет, но упрощает понимание метрик: высокий F1 значит, что модель не ушла в крайности: «Тут везде одуванчики!» / «Какие одуванчики? Тут пусто».
Но числа на тесте — это не главное. Главное — видимый результат на инференсе. В модель были поданы несколько настоящих фотографий, и вот, что получилось.
Вот это уже показатель. Domain gap — разрыв между синтетическими изображениями и настоящими фото — оказался минимальным. Модель, которая видела только «нейрослоп», хорошо обобщает на реальный мир.
А если объекта вообще не существует?
Теперь вернёмся к исходной постановке. Первый эксперимент показал, что концепция рабочая, однако одуванчики в качестве примера хоть и удобны, но не показывают истинную силу синтетики. Все генеративные модели знали, как выглядит одуванчик, а значит, им было относительно просто создать хорошую картинку. Генерация раскрывается в ситуации, когда даже сама модель не знает, что она рисует.
Представьте: нам нужно создать модель, которая должна обнаруживать объект, изображение которого существует в единичном экземпляре. Раньше это означало бы тупик, никакая аугментация (повороты, изменение цвета, обрезка и т. п.) не спасли бы. Но сейчас, благодаря технологиям, мы можем создать сколь угодно большой датасет, вопрос лишь в токенах.
Первым делом были сгенерированы референсы:
Далее, как и в первый раз, сгенерирован набор синтетических изображений, также применена аугментация:
Пример сгенерированного датасета
Применялся промпт, разделённый на несколько пунктов:
-
time,
-
weather,
-
environment,
-
composition,
-
style,
-
mood,
-
object.
Для каждого пункта были сгенерированы несколько вариантов, например, для time:
-
During a total solar eclipse with an unnatural twilight glow.
-
At the blue hour, just before sunrise, cold desaturated tones.
-
At midnight under a full moon with sharp cold shadows.
-
In the late afternoon with long diagonal shadows and warm haze.
-
At an ambiguous time — overcast sky with no shadows, flat light.
После чего скрипт создал тысячи промптов, комбинируя такие блоки:
-
Using the attached image as a reference, create a realistic photo featuring the object from the image.
-
The object should not be centered; avoid symmetry and repetitive compositions.
-
The object must be shown from a different angle than in the reference image.
-
Do not replicate the original perspective or lighting from the reference.
-
Time: at midnight under a full moon with sharp cold shadows.
-
Weather: in an unnatural heatwave with visible heat distortion shimmer.
-
Environment: in a shallow river or lake, partially submerged.
-
Composition: glimpsed between two close structures creating a narrow frame.
-
Style: linocut or woodblock print with rough black ink texture.
-
Mood: dreamlike and surreal, logic slightly broken.
-
Object: multiple objects at various depths, creating a sense of scale.
Синтетика: результат
Вот итог того, какие метрики мы имеем после обучения модели:
|
mAP@50 |
81.1% |
|
Precision |
86.6% |
|
Recall |
78.9% |
|
F1 |
82.6% |
Результат для всё ещё небольшого датасета очень хорош. Интересно, что баланс, по сравнению с первым экспериментом, сместился — Precision немного ниже, зато Recall выше (78.9% против 74.6%). Модель стала чуть смелее: находит больше объектов ценой небольшого роста ложных срабатываний.
Кстати, о ложных срабатываниях:

Матрица здесь интереснее, чем кажется на первый взгляд. Нюанс в том, что Artifact и Tower были намеренно сделаны похожими — одна цветовая гамма, один стиль, фиолетовое свечение, рваные кристаллические формы. Хотелось создать все условия для ложного срабатывания.
Но обмануть модель не удалось: путаницы между классами почти нет. Artifact приняли за Tower всего один раз, а обратно — вообще ни разу. Почти все ошибки сидят в столбце пропусков: модель не «перепутала» объект, а просто «не заметила» его. Это хороший знак — модель уверенно различает формы, несмотря на нарочитую схожесть. Ошибка возникает из-за осторожности: лучше пропустить, чем выдумать.
Зачем это всё?
Тем же GPT и Gemini можно дать изображение и попросить выделить на нём все объекты, как на референсе, они справляются отлично, способны к zero-shot, то есть предполагать, как бы объект выглядел в других условиях, под другим ракурсом.
Какова цена? Для одиночных запросов этого достаточно, но если это конвейер, то обработка тысяч изображений в день упирается в 2 проблемы: стоимость API и время ответа. Не забываем и про малый/отсутствующий датасет. Ещё сложнее ситуация с автономностью. Например, если мы хотим научить квадрокоптер следить и находить в поле коров/овец или анализировать местность, то модель должна работать локально и быть максимально компактной, так как не везде есть хороший и стабильный интернет, чтобы передавать в реальном времени большой поток данных.
Таким образом в сумме имеем 4 причины использовать синтетическую генерацию в паре с классическими моделями:
-
работа со сложными объектами,
-
скорость,
-
стоимость,
-
автономность.
Кроме того, синтетику можно использовать и в качестве дополнения к реальным данным, в качестве более продвинутой аугментации.
Итог
Раньше фраза «у нас нет данных» означала конец разговора, приговор. Сейчас она лишь значит, что перед обучением модели нужно эти данные сгенерировать.
Проведённые эксперименты продемонстрировали похожий на хорошо известный в мире LLM механизм дистилляции. Большая модель генерирует качественные данные, а маленькая и дешёвая использует их, чтобы стать умнее.
Конечно, это не серебряная пуля. Выборки всё ещё маленькие, генерация подкидывает свои артефакты, и на по-настоящему сложных сценах что-то наверняка отвалится. Но как доказательство концепции — более чем убедительно. Самое узкое место классического ML, данные, перестаёт быть стеной и превращается в вопрос нескольких удачных промптов.
А значит, в следующий раз, когда задача упрётся в «датасета нет, и взять негде», стоит вспомнить: его не обязательно искать, его можно сгенерировать.
Colab блокнот первого эксперимента с одуванчиками.
© 2026 ООО «МТ ФИНАНС»
Автор: daniilgorbenko


