По легенде, во время премьеры первого в истории человечества фильма «Прибытие поезда на вокзал Ла-Сьота» зрители устроили панику — они решили, что поезд настоящий и движется прямо на них. Больше века спустя на поезда смотрят нейросети — и даже принимают 3D-модели вагонов за реальные. Я Никита Каменев, видеоаналитик СИБУР Диджитал. Сегодня расскажу, как мы учили нейросеть распознавать прибытие поезда на 3D-моделях из Unreal Engine. Допустим, у нас есть сливо-наливная эстакада. Когда на неё приезжает поезд, опускаются мостики. На эти мостики выходят сотрудники завода и выполняют работы. Потом рабочие уходят, мостик поднимается и поезд уезжает. Для оптимизации этой рутины нужна нейросеть-классификатор, которая распознаёт: Положения поезда — стоит, движется или эстакада пустая; Положения мостиков — подняты или опущены; Рабочих — нужно отличить наших сотрудников от рабочих со стороны подрядчика; Наличие и отсутствие привязи — так как это высотные работы, нужно следить за безопасностью, и сообщать оператору, если на рабочем нет страховки. Разработку нейросети мы начали со сбора датасета – нам скинули изображения с камеры видеонаблюдения, на которых видно поезда и рабочих в разных положениях и состояниях. На сбор данных ушёл месяц, на обучение модели — ещё один. Потом тестирование и дообучение, в общем, здесь всё стандартно.  Модель в итоге оказалась настолько хороша, что привела к перевыполнению плана — и заказчик предложил масштабировать её на другие площадки.  Изначально мы обучили классификатор на данных с одной конкретной эстакады, которая находилась в закрытом помещении. Что будет, если показать нейросети прибытие поезда на уличную эстакаду?  Можно предположить, что модель, обученная на закрытой эстакаде, так же хорошо покажет себя и на открытой, но нет. Она не учитывает дождь, снег, время суток, засветы от солнца, туман и другие факторы. В текущем виде выпускать на другие площадки её нельзя — нужно дообучение. Но на уличных площадках факторов много: с учётом всех сезонов и погодных условий реальные данные в идеале нужно собирать целый год. Неужели нельзя побыстрее? Расширить датасет без сбора настоящих новых данных можно тремя способами: Аугментация — модифицируем то, что уже есть. Open source — скачиваем чужие данные из интернета и размечаем их под себя. GAN — обучить нейросеть на данных, сгенерированных другой нейросетью. Но проблема не только в деградации модели из-за разных погодных условий. Дело в том, что нейросеть ищет объекты на изображениях с камер видеонаблюдения — а они могут выдавать шумную картинку, где даже человек не всех рабочих найдёт. Например, сколько рабочих на этой фотографии? В этом случае не справилась даже нейросеть — например, приняла двух человек за одного, просто потому что они стояли рядом: Сначала мы пробовали решить эту проблему всё той же аугментацией. Брали сложные ракурсы и добавляли на них людей с других изображений, вырезая их в GIMP и фотошопе. Это сэкономило время — не нужно было ждать, когда мы получим те же сложные ракурсы с людьми. Но результаты выглядели нереалистично. Поэтому мы пошли другим путём. Так ли принципиально обучать нейросеть на настоящих кадрах и видео с камер, если алгоритм просто ищет контуры нужных объектов в разных состояниях? Нет — поэтому мы решили построить эстакаду в игровом движке Unreal Engine. Для генерации картинок взяли открытый сетпак с 3D-моделями разных модулей завода, построили пространство и пустили гулять ботов-рабочих. Вот как это выглядело: После обучения на таких данных точность определения рабочих возросла с 81% до 92%. Да, всего на 11% лучше, но эта разница чувствуется в проде. Тем не менее этого всё равно мало — заводы в Unreal Engine выглядят игрушечными, что бы мы ни делали. Вот бы был способ перенести реальные эстакады в пространство Unreal Engine… В теории, это можно сделать с помощью NeRF. NeRF — это Neural Radiance Field, нейросеть, которая создаёт 3D-модели на основе видео и фотографий. Чтобы сделать игровой завод из Unreal Engine менее игрушечным, мы попробовали действовать так: Берём телефон и устраиваем прогулку по заводу. Создаём реалистичную 3D-модель с NeRF. Закидываем эту модель в Unreal Engine и на её основе создаём датасет. Но обучение NeRF и генерация моделей — это отдельная задача. У нас был выбор из трёх инструментов: Luma AI, Nerfstudio и Instant NeRF.  Критерий/Инструмент Luma AI Nerfstudio Instant NeRF Простота установки Не требует установки Тяжело ставится на Windows, лучше на Linux Сложнее Luma AI, требует хорошую видеокарту Удобство использования Закрытый ящик, не надо кодить вообще Надо кодить, но пара команд и всё Кодить на более продвинутом уровне, чем в Nerfstudio Гибкость в обучении моделей Особо не настроить Проигрывает Instant NeRF в кастомизации Очень гибкий, можно управлять всеми параметрами В выборе инструмента важно учесть ещё и то, что нам все эти модели надо перенести в Unreal Engine. Так, Luma AI может при помощи отдельных плагинов экспортировать в платном формате .nvol с помощью плагина volinga или в бесплатном формате .luma. Nerfstudio тоже позволяет использовать volinga для экспорта. Но есть вариант лучше — можно экспортировать модель как облако точек для Blender и потом перенести её в движок. Та же схема применима и к Instant Nerf.  В итоге мы выбрали экспорт через Blender — формат .luma не позволяет использовать промышленные данные, которые не надо светить в открытых источниках. Полученные таким способом модели выглядели как из снов: Проблема моделей больших объектов в том, что результат сильно зависит от исходных данных. Мы эстакады обходили пешком и снимали видео на телефон с широкоугольным объективом. Из-за этого местами сетка ломалась и мы получали странные результаты с размытием и чёрными пятнами. В идеале для таких задач надо облететь объект на квадрокоптере. У нас такой возможности не было, поэтому мы дорабатывали модели из NeRF в движке. Модели поездов мы скачивали из открытых источников и сами анимировали, поднимали и опускали мостики, создавали разные условия. Получилась своего рода коллаба NeRF и Unreal Engine. Один из компонентов нашей исходной задачи — модель, которая обнаруживает привязь на рабочих. Человек сложнее поезда, состояний у него больше. Поэтому с учётом всех условий мы бы замучились делать тысячи картинок с 3D-человечками в разных позах. Чтобы ускорить процесс, мы использовали GAN — генеративно-состязательную нейросеть. Модель, которую мы обучаем, находит на изображениях человека и контур привязи. У привязи разных состояний будет меньше. Поэтому, вместо того, чтобы ставить 3D-человечков в разные позы, мы заставили GAN генерировать изображения людей на основе рандомных контуров привязи. Потом использовали сгенерированные картинки для обучения модели. Эти нейрорабочие выглядели искажёнными, но в целом похожими на людей. Но сразу возникает вопрос. Чтобы GAN что-то выдавала, ей надо скормить фотографии рабочих с привязями в разных ракурсах — из нашего реального датасета. Не будет ли она копипастить данные из датасета, и в итоге его не расширит? И неужели нельзя обойтись просто аугментацией? Мы задались этим вопросом и нашли на него ответ: F1 Score для модели, при обучении которой мы использовали только аугментацию, равен 82%. Аугментация вместе с данными из GAN повысила точность модели до 89%. Вернёмся к исходной задаче и модели, которая не обучалась на настоящих данных с открытой площадки. Если выпустить её на улицу без дообучения, она будет определять все нужные нам классы с точностью 67%. А после обучения на синтетических данных из игрового движка её точность возросла до 95%. И это модель, которая не видела настоящих фотографий уличной эстакады! Но нужно ли это вам? Зависит от задачи: Для большинства задач хватает открытых источников и настоящих данных с производств. Так, прирост в точности определения привязи на рабочих мы получили за счёт фотографий из гугла. Если задача сложная, данных мало и нужно быстрее обучить модель, можно подключить игровой движок.  А если модели из игрового движка недостаточно реалистичны, можно использовать NeRF для моделирования реальных объектов с производств. Значит ли это, что реальные данные не нужны? Нет, мы никогда от них не отказываемся — они всё равно полезны, даже если мы будем их собирать целый год. Постучали по дереву.  В общем, примерно так мы изворачиваемся ради высокого результата. А вы как решаете проблемы с нехваткой данных? Пишите в комментах, будет интересно обсудить!