В последнее время, в связи с растущим трендом виртуальной реальности, все более актуальными становятся съемка/монтаж/обработка видео в формате «видео 360».
В данной статье я хочу рассказать об одном эксперименте по обработке «видео 360», который хорошо иллюстрирует некоторые особенности такого формата. Забегая вперед скажу, что эксперимент потребовал реализации несложного алгоритма и, конечно, без написания программы не обошлось.
Что такое «видео 360»?
В рамках проекта Университета ИТМО Video360Production.com мы не только снимаем видео 360, но и попутно решаем целый «букет» сопутствующих задач — специализированная обработка панорамного видео, разработка интерактивных приложений для шлемов виртуальной реальности и многое другое.
«Видео 360» (панорамное видео), создается специальным образом — несколько видео камер смотрят «во все стороны», затем потоки синхронизируются и сшиваются в одну сплошную картинку. Одним из стандартов панорамного видео является сферическая развертка — сшитая сфера 360*360 разворачивается на кадр с соотношением сторон 2:1 (эквидистантная развертка), что позволяет кодировать панорамное видео в привычном H.264 и хранить во вполне смотрибельном виде.
При просмотре «видео 360» можно крутить мышкой или пальцем (на смартфоне, планшете), панорамное видео поддерживает YouTube и Facebook. Особенно эффектно оно смотрится в гарнитурах виртуальной реальности — Oculus Rift, Samsung Gear VR, Google Cardboard и др.
Вот так, например, выглядит концерт группы «Браво» в формате «видео 360»:
Панорамное видео может быть не только снято на видео камеру, но и получено из 3D-движков, как, например, трейлер «WARCRAFT: SKIES OF AZEROTH»:
Постановка задачи
Одной из типовых задач обработки видео является замена изображения — в программах видео монтажа есть соответствующие инструменты, позволяющие заменить статическое изображение или даже динамическое. В последнем случае используется трекинг «по ключам», что позволяет качественно и в (полу-)автоматическом режиме заменить заданный фрагмент изображения на некоторый другой.
А как обстоит дело с «видео 360»? Практика показывает, что все не так просто…
В качестве эксперимента я взял вот такое видео, собранное из UnrealEngine в формат панорамного видео и поставил задачу, на первый взгляд, несложную — очистить все баннеры, висящие сверху над «дорожкой», по которой едет тележка.
Кстати, этот ролик хорошо знают все, кто имел дело с Oculus Rift и аттракционами:
Задача оказалась не из простых.
Какие сложности возникают при попытке трекинга изображения в «видео 360»? Помимо трудностей конкретного примера (быстрое движение вагонетки, сложная текстура объектов) проявляется характерная особенность эквидистантной развертки — нетипичное искажение изображения — «изгибание» и растягивание по мере приближения к нижней/верхней части кадра. Оно и понятно — верхняя/нижняя часть кадра, строго говоря, соответствуют полюсам сферы, растянутым на ширину кадра.
Вот как это выглядит:
Издалека надпись почти прямоугольная, однако по мере приближения начинает закругляться кверху:
Когда вагонетка у самого баннера, начинается полное безобразие:
Из сопутствующих сложностей — высокая скорость движения на отдельных участках, из-за чего изображение баннера сильно размыто:
Алгоритм
Использование стандартных средств трекинга (например, в After Affects) для данных баннеров не дает хорошего результата — ключей получается очень много, они нестабильны, захватить изображение сложно. Из-за этого вставка белого фона (а точнее — фона цвета баннера, он не идеально белый) получается неточно, в некоторых случаях и вовсе мимо. Вручную править 7-15 ключей на каждом кадре — адская задача. Фактически, это покадровая реставрация ролика.
В связи с этим возникла идея оптимизировать данный процесс. Действительно, если посмотреть на задачу глазами программиста — баннеры должны неплохо распознаваться и вполне реально придумать несложный алгоритм, который позволил бы их «очистить». Также довольно очевидно, что программу проще сделать в интерактивном стиле, чтобы либо указывать алгоритму стартовую точку, либо указывать область для поиска.
Итак, после некоторых экспериментов, получилась такая последовательность действий:
- Переводим видео в «пачку» изображений, в соответствии с частотой кадров. Для данного ролика получился 1451 кадр JPG разрешением 4000*2000.
- Далее пишем интерактивную программу на C#/WPF, которая загружает очередной кадр оригинального видео, в указанной области выполняет поиск транспаранта, выделяет его границы и закрашивает внутренности указанным цветом. В случае ошибки у пользователя должна быть возможность поправить программу — изменив границы рабочей области, а также параметры алгоритма (искомый цвет, размер искомой области и пр.). К тому же, программа должна иметь возможность ZOOM для работы с мелкими деталями изображения.
- Если все хорошо, пользователь сохраняет обработанный кадр и переходит к следующему.
- Из кадров собирается итоговое видео.
Программа
Внешний вид:
Программа содержит следующие элементы:
1. В верхней части — отображается текущий кадр. На нем, при помощи красной рамочки, можно обозначить рабочую область — где алгоритм будет выполнять поиск баннера.
2. Снизу слева — увеличенный вид рабочей области. Алгоритм начинает работать автоматически и сразу показывает результат (очищенный баннер).
Размеры рамочки можно менять, что позволяет делать увеличение и работать даже с очень мелкими деталями:
3. Правая часть — панель настроек, содержащая имя файла, номер кадра, стрелки для перехода на следующий/предыдущий, опция «автосохранения при переходе к следующему».
Width и Height — позволяют регулировать ширину/высоту красной рамочки
Delta, BlockLength — параметры алгоритма.
Алгоритм работает следующим образом:
1. В заданной рамочкой области начинает искать точки, отличающиеся от заданного «фоного» цвета баннера не более чем на Delta. Delta можно менять, тем самым сужая или расширяя количество цветов.
2. Затем производится построковый анализ и остаются лишь те точки, которые образуют непрерывные группы длиной BlockLength, причем в каждой строчке по две — начальная и конечная (отмечены красным):
Таким образом, формируется граница баннера нужной толщины BlockLength, «изнутри» по фоновым точкам.
3. Блоки соединяются прямыми линиями с фоновым цветом (закраска баннера, отмечено желтым):
4. Вуаля!
С правильной настройкой значений по умолчанию для Delta и BlockLength алгоритм работает просто прекрасно! Часто можно листать кадры друг за другом без каких-либо дополнительных действий, иногда лишь подвигая рамку вслед за движением баннера по кадру. Иногда, параметры можно уточнить.
Кстати, если их выставить неправильно — т.е. выбрать слишком большой разброс цветов или слишком маленькую длину границы, то начнут зацепляться лишние точки:
С помощью данной программы я обработал все баннеры в ролике примерно за 1,5-2 часа.
Выводы
Конечно, данная задача является очень частной. Однако, на ее примере хорошо видны характерные особенности «видео 360» — искажение изображения, которое делает невозможным применение стандартных средств обработки видео.
Скорее всего, довольно скоро появятся плагины, которые будут учитывать эквидистантную проекцию панорамного видео (кстати, бывают и другие проекции...) и прямо в родном After Effects успешно справляться с этой и другими задачами.
А пока что… приходится изобретать. Надеюсь, данная статья будет кому-то полезна и поможет сократить время/силы при решении собственных задач.
Автор: Denis_Stolyarov