Обработка «видео 360», очистка изображения: алгоритм и его реализация на C#

В последнее время, в связи с растущим трендом виртуальной реальности, все более актуальными становятся съемка/монтаж/обработка видео в формате «видео 360».

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

image

Что такое «видео 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»? Помимо трудностей конкретного примера (быстрое движение вагонетки, сложная текстура объектов) проявляется характерная особенность эквидистантной развертки — нетипичное искажение изображения — «изгибание» и растягивание по мере приближения к нижней/верхней части кадра. Оно и понятно — верхняя/нижняя часть кадра, строго говоря, соответствуют полюсам сферы, растянутым на ширину кадра.

Вот как это выглядит:

image

Издалека надпись почти прямоугольная, однако по мере приближения начинает закругляться кверху:

image

image

image

Когда вагонетка у самого баннера, начинается полное безобразие:

image

image

Из сопутствующих сложностей — высокая скорость движения на отдельных участках, из-за чего изображение баннера сильно размыто:

image

Алгоритм


Использование стандартных средств трекинга (например, в After Affects) для данных баннеров не дает хорошего результата — ключей получается очень много, они нестабильны, захватить изображение сложно. Из-за этого вставка белого фона (а точнее — фона цвета баннера, он не идеально белый) получается неточно, в некоторых случаях и вовсе мимо. Вручную править 7-15 ключей на каждом кадре — адская задача. Фактически, это покадровая реставрация ролика.

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

Итак, после некоторых экспериментов, получилась такая последовательность действий:

  1. Переводим видео в «пачку» изображений, в соответствии с частотой кадров. Для данного ролика получился 1451 кадр JPG разрешением 4000*2000.
  2. Далее пишем интерактивную программу на C#/WPF, которая загружает очередной кадр оригинального видео, в указанной области выполняет поиск транспаранта, выделяет его границы и закрашивает внутренности указанным цветом. В случае ошибки у пользователя должна быть возможность поправить программу — изменив границы рабочей области, а также параметры алгоритма (искомый цвет, размер искомой области и пр.). К тому же, программа должна иметь возможность ZOOM для работы с мелкими деталями изображения.
  3. Если все хорошо, пользователь сохраняет обработанный кадр и переходит к следующему.
  4. Из кадров собирается итоговое видео.

Программа


Внешний вид:

image

Программа содержит следующие элементы:

1. В верхней части — отображается текущий кадр. На нем, при помощи красной рамочки, можно обозначить рабочую область — где алгоритм будет выполнять поиск баннера.
2. Снизу слева — увеличенный вид рабочей области. Алгоритм начинает работать автоматически и сразу показывает результат (очищенный баннер).

Размеры рамочки можно менять, что позволяет делать увеличение и работать даже с очень мелкими деталями:

image

3. Правая часть — панель настроек, содержащая имя файла, номер кадра, стрелки для перехода на следующий/предыдущий, опция «автосохранения при переходе к следующему».

Width и Height — позволяют регулировать ширину/высоту красной рамочки
Delta, BlockLength — параметры алгоритма.

Алгоритм работает следующим образом:

1. В заданной рамочкой области начинает искать точки, отличающиеся от заданного «фоного» цвета баннера не более чем на Delta. Delta можно менять, тем самым сужая или расширяя количество цветов.
2. Затем производится построковый анализ и остаются лишь те точки, которые образуют непрерывные группы длиной BlockLength, причем в каждой строчке по две — начальная и конечная (отмечены красным):

image

Таким образом, формируется граница баннера нужной толщины BlockLength, «изнутри» по фоновым точкам.
3. Блоки соединяются прямыми линиями с фоновым цветом (закраска баннера, отмечено желтым):

image

4. Вуаля!

С правильной настройкой значений по умолчанию для Delta и BlockLength алгоритм работает просто прекрасно! Часто можно листать кадры друг за другом без каких-либо дополнительных действий, иногда лишь подвигая рамку вслед за движением баннера по кадру. Иногда, параметры можно уточнить.

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

image

С помощью данной программы я обработал все баннеры в ролике примерно за 1,5-2 часа.

Выводы


Конечно, данная задача является очень частной. Однако, на ее примере хорошо видны характерные особенности «видео 360» — искажение изображения, которое делает невозможным применение стандартных средств обработки видео.

Скорее всего, довольно скоро появятся плагины, которые будут учитывать эквидистантную проекцию панорамного видео (кстати, бывают и другие проекции...) и прямо в родном After Effects успешно справляться с этой и другими задачами.

А пока что… приходится изобретать. Надеюсь, данная статья будет кому-то полезна и поможет сократить время/силы при решении собственных задач.
Поделиться публикацией
Комментарии 10
    +2
    Коммент про 360, не совсем относительно статьи.

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

    Вид

    Сферические видео имеют ужасные искажение на "полюсах". И даже качество картинки на "экваторе" тоже оставляет желать лучшего.
    Мир с перспективы мухи смотрящей через замочную скважину это сомнительное удовольствие.

    Энкодинг

    В связи с тем, что даже малейшие изменения на полюсах приводят к изменению кадра на 30% поверхности ("верх" и "низ" занимают примерно по 30% вертикального разрешения), в результате весь битрейт занимают векторы движения на полюсах которые мало того что ужасно выглядят и на них никто не смотрит, так они еще и занимают половину "файла". В результате все CBR профили превращают видео в "мыло"

    Если кто-то занимается 360 видео, бегите от сферической проекции как можно быстрее.
      0
      Все верно. Однако по факту все видео 360 сейчас в сфере — камеры сшивают именно в сферу, а также YouTube и Facebook поддерживают именно сферическую развертку.
      Почему именно так получилось — вопрос для размышлений.
        0
        Фейсбук куб. Не сфера.

        Кто-то начал делать по тупому и yt пришлось это г. поддерживать.
          0
          Спасибо, насчет фейсбука не знал.
      0
      Относительно задачи. Попробуйте перевести проекцию в куб и повторить задачу :)
        0
        Разумеется, в кубе гораздо проще, т.к. нет сферических искажений. В этом случае задача сводится к относительно стандартному трекингу объектов на видео.
          0
          Тогда стоит вопрос: к чему эти извращения?)
        0
        А кто может объяснить, почему качество готовых видео уже присутствующих на youtube такое низкое?
        В развёртке вроде очень даже ничего, а вот сшитое в сферу сразу пикселизированное получается у многих.
          +1
          Все просто.

          Пиксели

          • Field of view на YT примерно 65° по "горизонтали" и примерно 60° по вертикали
          • Возьмем видео из варкрафта которые автор дал выше.
          • Самое большое разрешение это 2560 х 1440
          • Следовательно реальная картинка которую "видно за раз" 2560 / 360 65 x 1440 / 180 60 ~~~> 460 x 480
          • 80% скачанного и декодированного (попробуйте открыть видео 8k, процессор умрет) видео идет в мусорку
          • 240p! Here we meet again!!!

          Энкодинг

          • Писал выше
          • Профили на YT делают энкодинг под конкретное значение битрейта. Это условие стандарта MPEG-DASH
          • Большинство байт в видео "уходит" на идиотский "верх" и "низ".
          • В связи с этим на середину, гда обычно все самое интересное и происходит остается и того меньше.
          • Результат мыло

          Картинко для куба

          0
          Задачу можно решить геометрически: матрицу искажения мы знаем, рассчитываем обратную матрицу проектирования (узнаем радиус сферы, если не знаем). Трекая точки на последовательности, находим положение камеры в каждый момент. Итого, найдя 3д координаты углов таблички, мы на каждом кадре знаем, где она и её искаженная поверхность.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое