Играем В Тетрис В Ar

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

Недалеко от меня было всего одно подходящее для этого здание.

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

Источник Чаще всего сейчас используются 2 варианта реализации дополненной реальности:

  • безмаркерный, т.е.

    положение камеры определяется перемещением ключевых точек в ее видеопотоке;

  • изображение как маркер, относительно которого находится положение камеры.

Эти реализации не требуют специальной подготовки или особых условий.

Есть еще один вариант реализации — распознавать конкретный объект и использовать его как маркер.

Это требует как минимум его наличия, но дает возможность визуально его контролировать.

Одним из методов такого распознавания является обнаружение объекта по его краям.

Имеет ограничения — объект-маркер должен иметь четко выраженные края, т.е.

объект, скорее всего, должен быть однотонным.

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

Играем в тетрис в AR

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



Выполнение

На Qt. Этот фреймворк позволяет работать на разных платформах и одновременно на C++.

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

Хоть Qt и не очень хорошо работал с Android (долгий запуск, глючная отладка), это всё компенсировалось возможностью отладки алгоритма на десктопе.

3D-графика визуализировалась с использованием необработанного OpenGL, встроенного в Qt. Работа с камерой осуществлялась средствами Qt. Для отладки записывалось видео, и было довольно удобно заменить видеопоток камеры видеопотоком из файла.

Вывод осуществлялся средствами qml. Совместная работа qml и OpenGL прошла не без проблем, но мы не будем на этом останавливаться.

Для обработки изображений включена библиотека OpenCV.

Алгоритм отслеживания

Теперь перейдем к самому интересному — алгоритму слежения за объектом по его краям.

И давайте начнем с выделения краев на изображении.

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

Его можно использовать в качестве детектора линии.

Преобразование Хафа .

Однако этот путь мне кажется не очень правильным, так как преобразование Хафа довольно дорогое, к тому же этот детектор не очень надежный (это субъективно, возможно, все зависит от задачи).

Вместо этого давайте пойдем другим, более общим путем.

Мы не будем учитывать, что наши линии прямые, а просто будем работать на бинарном изображении.

Наличие краев будет закодировано в двоичное изображение.

Те.

пиксель со значением, равным нулю, означает, что в этом месте есть край, значение пикселя больше нуля означает, что края нет. Это изображение можно получить с помощью Детектор границ Канни или с простым пороговое преобразование .

Эти алгоритмы можно найти в OpenCV. У OpenCV теперь есть еще одна полезная для нас функция — расстояниеПреобразование , который принимает на вход двоичное изображение и выводит изображение, пиксели которого кодируют расстояние до ближайшего нулевого пикселя.

Теперь давайте предположим, что у нас уже есть первое хорошее приближение того, где должна располагаться наша модель.

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

С помощью изображения от distanceTransform мы уже можем это сделать.

А затем запускаем алгоритм оптимизации функции, меняя лишь нашу аппроксимацию положения объекта в пространстве.

В результате наше приближение должно достаточно точно описывать фактическое положение объекта.

В результате алгоритм можно разделить на два этапа:

  1. Предварительная обработка изображения — бинаризация, фильтрация и применение функции distanceTransfrom.
  2. Отслеживание — оптимизация функции ошибок.



Предварительная обработка изображений

На этом этапе необходимо выделить края на изображении.

Можно использовать детектор границ Канни, но в нашем случае лучше работает обычное пороговое преобразование или его адаптивная версия (в OpenCV это функции Threshold или AdaptiveThreshold).

Понятно, что такое изображение будет иметь шум, поэтому необходима фильтрация.

Сделаем это следующим образом — выделим контуры с помощью функции OpenCV. найтиКонтуры и удалите сегменты, которые слишком малы или недостаточно похожи на линии.

Результат обработки можно увидеть на изображении:

Играем в тетрис в AR

Последовательно: исходное изображение -> после порогового преобразования -> после фильтрации.

Это изображение уже достаточно четко говорит нам, где нужное ребро, а где его нет. После этого мы используем функцию distanceTransform, и в результате у нас будет информация о том, насколько далеко каждая точка находится от края.

Обозначим полученное изображение как

Играем в тетрис в AR

.

Вот как это выглядит в нормализованном и визуализированном виде:

Играем в тетрис в AR

Далее нам понадобятся некоторые математические инструменты.



Алгоритм оптимизации функции
Оптимизация функции — это задача поиска минимума функции.

Если мы имеем дело с линейной системой уравнений, то найти минимум достаточно просто.

Представим систему уравнений в матричной форме:

Играем в тетрис в AR

, то наше решение:

Играем в тетрис в AR

.

Если у нас есть переопределенная система уравнений, то мы можем использовать метод наименьших квадратов :

Играем в тетрис в AR

.

Если наша функция нелинейная, то задача усложняется.

Чтобы найти минимум, вы можете использовать Алгоритм Гаусса-Ньютона .

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

  1. Предполагается, что у нас уже есть некоторое начальное приближение решения

    Играем в тетрис в AR

    , который мы будем уточнять итеративно.

  2. Используя расширение Тейлора, мы можем приблизить нашу нелинейную функцию к линейной в точке текущего приближения.

    Решаем полученную линейную систему уравнений методом наименьших квадратов, получая

    Играем в тетрис в AR

    .

    Полученное решение не будет решением, но оно будет ближе, чем текущие приближения.

  3. Заменить текущее приближение

    Играем в тетрис в AR

    полученное решение

    Играем в тетрис в AR

    и переходим к шагу 2. Повторяем это до тех пор, пока разница между

    Играем в тетрис в AR

    И

    Играем в тетрис в AR

    не упадет ниже определенного значения.

Давайте рассмотрим алгоритм немного подробнее.

Позволять

Играем в тетрис в AR

- рабочая функция,

Играем в тетрис в AR

— вектор заранее известных значений функции.

Учитывая идеальное решение уравнения

Играем в тетрис в AR

следующее утверждение верно

Играем в тетрис в AR

.

Но у нас есть только приблизительное представление о нем.



Играем в тетрис в AR

.

Тогда мы обозначим вектор ошибки из этого приближения как:

Играем в тетрис в AR

.

И общая ошибка функции будет:

Играем в тетрис в AR

.

Теперь найдя такой

Играем в тетрис в AR

, при котором

Играем в тетрис в AR

достигнет минимума, мы получим лучшее приближение решения

Играем в тетрис в AR

.

Начиная с подхода

Играем в тетрис в AR

будем итеративно аппроксимировать его, получая на каждой итерации

Играем в тетрис в AR

.

Для этого нам нужно просчитать каждую итерацию Матрица Якоби для функции

Играем в тетрис в AR

для текущего приближения, состоящего из производных нашей функции:

Играем в тетрис в AR

И следующее приближение задается как:

Играем в тетрис в AR

.

Часто задачи структурированы таким образом, что мы имеем большой объем данных, независимых друг от друга (только по значениям

Играем в тетрис в AR

).

В результате общая матрица Якобиана оказывается очень разреженной.

Есть способ оптимизировать расчеты.

Предположим, у нас есть общая функция, рассчитанная по набору точек.

От дж -й балл, который мы получаем

Играем в тетрис в AR

.

Вместо вычисления матрицы Якобиана

Играем в тетрис в AR

для всей функции мы вычисляем матрицу Якобиана специально для

Играем в тетрис в AR

и обозначим это как:

Играем в тетрис в AR

.

Тогда следующее приближение будет иметь вид:

Играем в тетрис в AR

.

Кроме того, это изменение позволяет распараллеливать вычисления.

Может случиться так, что следующее значение

Играем в тетрис в AR

даст большую ошибку, чем

Играем в тетрис в AR

.

Для решения этой проблемы можно использовать модификацию алгоритма — Алгоритм Левенберга-Марквардта .

Добавить значение

Играем в тетрис в AR

в нашу формулу:

Играем в тетрис в AR

, Где

Играем в тетрис в AR

является единичной матрицей.

Значение

Играем в тетрис в AR

выбирается следующим образом:

  • сначала оно имеет некоторое достаточно малое значение (такое, что алгоритм сходится);
  • тогда, если ошибка связана с

    Играем в тетрис в AR

    больше, чем

    Играем в тетрис в AR

    , затем увеличьте значение

    Играем в тетрис в AR

    и попытайтесь вычислить ошибку для

    Играем в тетрис в AR

    снова.

Чем более нелинейна функция

Играем в тетрис в AR

, тем больше должно быть значение

Играем в тетрис в AR

.

Однако чем выше значение

Играем в тетрис в AR

, тем медленнее сходится алгоритм.

Завершим алгоритм, когда

Играем в тетрис в AR

отличается от

Играем в тетрис в AR

до достаточно малого значения и принять

Играем в тетрис в AR

как решение.

Алгоритм достаточно универсален и может использоваться для самых разных задач.



Математическая модель отслеживания
Поскольку мы имеем дело с координатами в пространстве, то понятно, что нужно уметь манипулировать этими координатами.

Предположим, у нас есть некоторый набор точек

Играем в тетрис в AR

.

И нам нужно повернуть их вокруг точки с нулевыми координатами.

Вероятно, проще всего использовать матрицу вращения.

р , описывающая требуемый поворот:

Играем в тетрис в AR

.

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

Играем в тетрис в AR

.

Таким образом, вы можете менять положение объекта в пространстве по своему усмотрению.

Оказывается, координаты объекта задаются трёхмерной матрицей р и трехмерный вектор т , т.е.

12 параметров.

Более того, эти параметры не являются независимыми друг от друга; компоненты матрицы вращения связаны между собой определенными условиями.

Поэтому с точки зрения использования этих параметров при оптимизации функции эти параметры не являются лучшим решением.

Параметров больше, чем степеней свободы; между ними существует зависимость.

Есть еще одна форма ротации – Формула вращения Родрига .

Это вращение задается тремя параметрами, образующими трехмерный вектор.

Нормализованный вектор — это ось вращения, а длина этого вектора — это угол вращения вокруг этой оси.

Зададим функцию вращения вектора в :

Играем в тетрис в AR

использование параметров р Формулы Родригеса.

Отсюда мы получаем следующую формулу:

Играем в тетрис в AR

.

И в результате мы можем указать координаты положения объекта 6-мерным вектором:

Играем в тетрис в AR

Получаем следующую формулу:

Играем в тетрис в AR

.



Модель камеры-обскуры
Теперь опишем простую математическую модель камеры, используемой в проекте:

Играем в тетрис в AR

Где

Играем в тетрис в AR

— фокусное расстояние в пикселях;

Играем в тетрис в AR

— оптический центр также в пикселях.

Это индивидуальные параметры камеры, которые называются внутренними параметрами камеры.

Обычно эти параметры известны заранее.

В данном проекте эти параметры подбирались на глаз.

Данная модель не учитывает искажения объектива камеры ( искажение ).

Предположим, их не существует. С помощью этой модели мы получаем центральную проекцию, все точки которой стремятся к оптическому центру, чем дальше они расположены, тем дальше от камеры.

Таким образом мы получаем эффект сужающейся железной дороги:

Играем в тетрис в AR

В пространстве камера совмещена с осью я , плоскость изображения параллельна плоскости ху .

Дополним нашу модель возможностью перемещения в пространстве:

Играем в тетрис в AR

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

В этой модели нам остаются неизвестными параметры взаимного положения камеры в пространстве.



Играем в тетрис в AR

.

Эти параметры называются внешними характеристиками камеры (внешние параметры камеры).



Отслеживание
Реализовано без инструментов OpenCV. Во-первых, нам нужно получить функцию ошибок для нашего приближенного решения, которое было описано выше.

И опишем его расчет пошагово:

  1. Выбираем такие края модели слежения, которые видны, исходя из параметров текущей аппроксимации.

  2. Превращаем выбранный набор ребер в фиксированный набор точек для упрощения вычислений.

    Можно, например, взять с каждого края n-ное количество точек или (более правильный вариант) выбрать такое количество, чтобы между точками было фиксированное расстояние в пикселях.

    Назовем их контрольными точками (в проекте: controlPoint — контрольные точки и controlPixelDistance — то самое фиксированное расстояние в пикселях).

  3. Проецируем контрольные точки на изображение.

    Благодаря расстояниеИзображение мы можем получить расстояние проекции контрольной точки до края изображения.

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

    расстояние до края должно быть равно нулю.

    На основании этого получаем ошибку для конкретной контрольной точки:

    Играем в тетрис в AR

    .

  4. Мы получаем следующую функцию ошибки:

    Играем в тетрис в AR

Теперь осталось найти минимум ? .

Для этого воспользуемся описанным выше алгоритмом Левенберга-Марквардта.

Как мы уже знаем, алгоритм требует вычисления матрицы Якобиана, т.е.

производных функций.

Можно использовать численное определение производных.

Вы также можете использовать некоторые готовые решения этого алгоритма.

Однако в этом проекте все было написано вручную, поэтому я опишу полный вывод всего решения.

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

Выше уже было описано, что в этом случае можно рассматривать эти уравнения независимо друг от друга, вычисляя матрицу Якобиана конкретно для каждого.

Давайте рассмотрим это по порядку, используя правила дифференцирования сложной функции:

Играем в тетрис в AR

Обозначим

Играем в тетрис в AR

, Затем

Играем в тетрис в AR



Играем в тетрис в AR

Отсюда:

Играем в тетрис в AR

Далее мы обозначим

Играем в тетрис в AR

И

Играем в тетрис в AR

, Затем:

Играем в тетрис в AR

Производные изображения расстояниеИзображение находятся численно.

И для расчета векторов

Играем в тетрис в AR

И

Играем в тетрис в AR

вам нужно будет найти производные, используя формулу вращения Родрига.

Я нашел якобиан, используя эту формулу в публикации «Компактная формула для производной трехмерного вращения в экспоненциальные координаты» Гильермо Гальего, Энтони Йецци :

Играем в тетрис в AR

, Где р — матрица вращения, полученная по формуле Родригеса из вектора вращения

Играем в тетрис в AR

;

Играем в тетрис в AR

— точка, которую мы вращаем; я - единичная матрица;

Играем в тетрис в AR

.

Как мы видим здесь, у нас происходит деление на длину вектора вращения, и если вектор равен нулю, то формула уже не работает. Вероятно, это связано с тем, что при нулевом векторе не определена ось вращения.

Если вектор вращения очень близок к нулю, то используем такую формулу:

Играем в тетрис в AR

.

Осталось только покрасить

Играем в тетрис в AR

И

Играем в тетрис в AR

(здесь индекс дж опущено):

Играем в тетрис в AR



Играем в тетрис в AR

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

У этого алгоритма есть несколько проблем.

Во-первых - точность.

В результате глобальное положение камеры незначительно меняется от кадра к кадру.

Мы можем это немного исправить.

У нас есть априорная информация, что положение камеры не может резко меняться от кадра к кадру.

И мы можем уменьшить этот джиттер, добавив в функцию дополнительные уравнения.

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

Глобальная позиция — это локальная точка с нулевыми координатами, поэтому ее можно определить следующим образом:

Играем в тетрис в AR

Мы запоминаем положение предыдущего кадра в предыдущаяGlobalPosition .

Теперь предыдущая позиция должна быть близка к нулю, т.е.

длина вектора

Играем в тетрис в AR

должно быть достаточно маленьким.

Те.

Необходимо минимизировать, помимо других значений невязки, вектор д .

Для определения степени влияния данной модификации введем значение

Играем в тетрис в AR

и умножить перед добавлением вектора д на

Играем в тетрис в AR

:

Играем в тетрис в AR

Теги: #Android #Разработка Android #математика #Алгоритмы #AR и VR #дополненная реальность #AR #tetris #дополненная реальность #Qt #отслеживание на основе моделей

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.