python

Стабилизация видео с движущейся камеры, или как перевести всё в неподвижную систему координат

  • суббота, 22 августа 2020 г. в 00:30:05
https://habr.com/ru/post/516122/
  • Python


Сейчас возможности Computer Vision (CV) полностью перекраивают ландшафт рынка Public Safety solutions. В то время, как традиционными системами видеонаблюдения уже не просто никого не удивить, а странно не найти её в любом общественном месте, использование ИИ в данной области всё ещё вновинку.


Как R&D департамент Oxagile, мы исследуем применение CV для различных бизнес-задач в сфере Public safety. В этом посте мы предлагаем вариант перевода видео с движущейся камеры в неподвижную систему координат для последующего анализа.




Допустим у нас есть какое-то видео и мы хотим построить для него неподвижную систему координат, чтобы оценивать расположение объектов относительно друг друга.


Зачем это нужно? Очень часто в задачах public surveillance видео, которое нужно анализировать, снято на движущуюся камеру. Из-за этого возникает несколько проблем в определении положения объектов относительно друг друга:


  • Непонятно, чем вызвано изменение координат объекта: движется камера или сам объект;
  • При смене сцены из-за поворота камеры разные объекты могут получить одни и те же координаты, даже если объекты были статичными.

image
Рисунок 1- Одинаковые объекты имеют разные координаты из-за движения камеры


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


  1. Определить начало координат;
  2. Сопоставить между собой два последовательных фрейма;
  3. Найти преобразование, которое будет переводить координаты объекта на текущем фрейме в координаты относительно начала координат, при этом учитывать все движения камеры (поворот, перемещение, наклон и т.д.).

image
Рисунок 2-проективное преобразование


О каждом пункте подробнее:


  1. За начало координат возьмем верхний левый угол первого фрейма.
  2. Введем определение: особой будет называться такая точка изображенного объекта, которая с большой вероятностью будет найдена на другом изображении этого же объекта. С помощью таких особых точек мы и будем сопоставлять между собой последовательный фреймы. Матчатся особые точки одного объекта на разных изображениях между собой по совпадению дескприторов. Здесь в качетсве алгоритмов для поиска особых точек и их дискрипторов мы использовали SIFT, SURF и ORB. Три типа особых точек использовались для того, чтобы покрыть максимально возможную площадь фрейма. Важно отметить, что фреймы могут быть связаны с помощью разных типов точек, и можно использовать другие алгоритмы для их поиска, но в данной версии мы выбрали иммено эти три.


Рисунок 3-matching visualization


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

Что нужно знать о гомографии


Гомография характеризуется своей матрицей Н:


image


  • a, e — масштабирование по x и y соответственно;
  • b, d — сдвиг по осям (вместе с a и e влияют на поворот);
  • c, f — смещение по осям;
  • g, h — изменение перспективы.

Используя эту матрицу, можно описать изменение координат одного объекта между двумя фреймами, если это изменение вызванно движением камеры. Получить из (x,y) новые координаты (x',y') можно следующим образом:


image
или в матричнов виде:


$t(x',y',1)=H(x,y,1) (1)$


Пайплайн:


Давайте рассмотрим работу алгоритма на примере обработки k-ого фрейма.
Пусть есть N последовательных фреймов — (f1,..., fN). В качестве начала координат зафиксируем левый верхний угол первого фрейма. Определим matching points как точки, которые связывают fk и fk-1.


Введем следующие обозначения:


О — начало координат;
(Xk, Yk)=((x1k, y1k),…, (xnk, ynk)) – координаты n matching points;
(X'k, Y'k) =((x'1k, y'1k),…, (x'nk, y'nk)) – координаты n matching points в неподвижной системе координат;
(X''k, Y''k) =((x''1k, y''1k),…, (x''nk, y''nk)) – k — координаты n matching points в систееме координат, где ее началом является левый верхний угол fk-1.
Hk – матрица гомографии, которая описывает движение камеры между fk-1 и fk.

Считаем, что есть набор общих точек для двух фреймов и их оригинальные координаты относительно фрейма.


Необходимо из (Xk, Yk) получить (X'k, Y'k). Найти матрицу гомографии между f1 и fk не всегда возможно, т.к. за время движения камеры сцена могла кардинально поменяться и фреймы могут не содержать общих объектов. Поэтому найдем матрицу перехода Hk.


Считаем, что уже найдена последовательность таких матриц для предыдущих фреймов (H1,…, Hk-1). Если матрица Hk будет описывать изменения между координатми (Xk-1, Yk-1) и (Xk, Yk), то мы не учтем, что взаимное расположение объектов могло сильно измениться с начала видео.


Рассмотрим рисунок 3:


image


Рисунок 3 — пример движения камеры, при котором произошло масштабирование объектов

Здесь показан пример такого движения камеры, при котором происходит масштабирование объектов. Если на текущем фрейме координата объекта изменилась на a пискелей:
x1k = x1k-1a, это не значит, что он переместился на a координат в неподвижной системе: x'1k = x1ka, это очень хорошо видно на рисунке 3. Поэтому, при поиске преобразования между двумя фреймами нужно учесть все трансформации, которые произошли с первого кадра.


Как это сделать?
Описать передвижение камеры между всеми предыдущими парами последовательных фреймов можно с помощью известных матриц гомографии (H1,…, Hk-1). Но необходимо найти такую суперпозицию этих матриц, которая будет описывать полное движение от 1 до k-1 кадра и позволит найти координаты mathcing points на fk-1 в неподвижной системе. Если посмотреть на формулу (1), становится понятно, что такая суперпозиция — это перемножение матриц всех предыдущих переходов.


$H_{sup}=H_1(H_2(H_3...))(2)$


Таким образом, для того, чтобы найти матрицу гомографии, описывающую движение камеры между fk-1 и fk, необходимо: умножить оригинальные координаты (Xk-1, Yk-1) и (Xk, Yk) на суперпозицию матриц (формула (2)), и уже для полученных координат (X'k-1, Y'k-1) и (X''k, Y''k) искать матрицу Hk. В результате, получим преобразование, которое переведет координаты объекта на этом фрейме (x1k, y1k) в координаты этого объекта относительно начала координат (x'1k, y'1k).


$t(x',y',1)=H_{sup} (x,y,1) (3)$


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


  • Получаем "грязные" matching points с координатами ((x1k, y1k),… ,(x'nk, y'nk)), которые включают в себя точки и на подвижных объектах
  • Находим матрицу гомографии H которая переведет координаты k-ого фрейма в плоскость k-1 фрейма.
  • Применяем ее к найденым точкам получаем их новые координаты ((x'1k, y'1k),… ,(x'nk, y'nk))
  • Фильтруем точки следующим образом:
    • Ищем расстояние на которое переместилась каждая точка по сравнению с предыдущим фреймом;
    • Группируем. Округляем перемещение до целых, и точки с одинаковым пермещением попадают в одну группу;
    • Если кол-во точек в группе меньше трешхолда (в скрипте этот порог равен LENGTH_ACCOUNTED_POINTS len(matching points)*), считаем, что это точки, которые зацепились за движущийся объект, и удаляем их из рассмотрения.

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


Но найденная на грязных точках матрица будет описывать не только движение камеры, но и частично движение движущихся объектов. И, следовательно, координаты объектов, движение которых будет описано достаточно точно, не изменятся и попадут в группу с неподвижными объектами. Tаким образом, матрица гомографии может быть посчитана неточно. В связи с этим, в качестве улучшения фильтрации рассматривается внедрение motion video segmentation.


О проекте.


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


  • evenvizion_component.py
  • evenvizion_visualization.py
  • compare_evenvizion_with_original_video.py

evenvizion_component.py
Реализация самого алгоритма неподвижной системы координат и всех основных результатов, происходит в файле evenvizion_component.py. На вход скрипт принимает путь к видео, на выходе возвращает json с матрицами гомографии, описывающими перемещение между fk-1 и fk. Важно, в json записаны матрицы, описывающие перемещение только между двумя фреймами. Чтобы получить координаты в неподвижной системе, необходимо сначала получить суперпозицию матриц, о которой было рассказано выше.


Если же вы хотите пересчитать координаты каких-то определенных объектов, то необходимо указать путь к json файлу в --path_to_original_coordinate с этими объектами и вы получите recalculated_coordinates.json с пересчитанными координатами, а также их визуализацию.
Формат json файла:


{"frame_no": [{"x1": x coordinate, "y1": y coordinate}, ...], ...}

Таким образом после работы evenvizion_component.py скрипта, вы получаете 3 визуализации (управлять matching and heatmap визуализациями можно с помощью аргументов --show_matches и --visualize_fixed_coordinate_system соответственно).


evenvizion_visualization.py и compare_evenvizion_with_original_video.py используются исключительно для получения визуализаций работы компонента.


Больше про аргументы и константы Вы можете прочитать в README.


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


Визуализация и интерпретация результатов:


Визуализация matching points — matching visualization:


image
Рисунок 5 — matching visualization


Ее описание приводилось выше.
Для демонстрации того, как работает именно неподвижная система координат была разработана следующая визуализация (heatmap visualization):


image
Рисунок 6 — heatmap visualization


В данной визуализации фрейм разбивается на 20 прямоугольников, и на каждом кадре координаты центра прямоугольника пересчитываются в новой системе координат, то есть можно посмотреть как неподвижные объекты сохраняют свои координаты по мере движения камеры. Здесь используется окрашивание фрейма в зависимости от того, насколько далеко от начала координат расположен объект. Цвет окрашивания определяется следующим образом: вычисляется расстояние от объекта до начала координат r =sqrt(x2+y2), нормализуется с помощью агрумента heatmap_constant и в зависимости от полученного значения окрашивается в определенный цвет, диапазон цветов: 0 — синий, 1 — красный.



Рисунок 7 — fixed_coordinate_system_visualization


Если Вы указали json с координатами объектов, которые необхомо пересчитать, вы получите fixed_coordinate_system_visualization (рисунок 7)


evenvizion_visualization.py и compare_evenvizion_with_original_video.py используются для визуализации стабилизации камеры, и покрывают только перемещение камеры (масштабирование и поворот такая визуализация не учитывает). На рисунках 8 и 9 представлены результаты работы этих скриптов соотвественно


image
Рисунок 8 — visualize_camera_stabilization


image
Рисунок 9 — original_video_with_EvenVizion


Known issues


N/a координаты. Когда matching points цепляются за подвижные объекты, то есть фильтрация работает недостаточно хорошо, и когда угол поворота камеры больеш 90 градусов, координаты не могут быть определены. В качетсве решения первой проблемы в данный момент рассматривается внедрение video motion segmentation, чтобы, учитывая характер движения, отделять static points от motion points. А в качетсве решения второй — переход к цилиндрической системе координат.


Матрица Н не определена. Для поиска гомографии необходимо минимум 4 matching points, но бывают случаи, когда 4 точки невозможно найти, и матрицы гомографии Н=None. В данной версии алгоритма такие случаи обрабатываются следующим образом: если аргумент none_H_processing стоит True, то считаем что матрца предыдущего фрейма будет соответствовать матрице текущего: Hk=Hk-1. Если же False, то H — единичная матрица, то есть никакого движения на данном кадре не было. Необходимо продумать более качетсвенную обработку таких ситуаций.


Погрешность. Имеет место погрешность в координатах. Некачественно полученная матрица гомографии искажает результаты пересчета координат. Причины:


  • Некачественная фильтрация. Если точки зацепятся за движущийся объект, то матрица гомографии будет описывать не только движение камеры, но и самостоятельное движение объектов (например, ходьбу человека).
  • Ипользование встроенной функции findHomography() модуля opencv. Эта функциия уже предполагет наличие погрешности в расчете матрицы гомографии.

Выводы


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