Привет!! Меня зовут Джаянт, и ниже приводится руководство по созданию вашей первой программы дополненной реальности с использованием Python и OpenCV. Этот проект был заданием, которое я получил в моем курсе по компьютерному зрению в бакалавриате, который я разбил здесь, шаг за шагом.

Надеюсь, после изучения этого руководства у вас будет что-то похожее или даже лучше.

Заявление об ограничении ответственности: для этого потребуются базовые знания Python и OpenCV, поэтому, если вы раньше не использовали OpenCV, я бы порекомендовал вам сначала пройти вводное руководство. Я вставил фрагменты кода, чтобы лучше понять, что происходит. Рекомендуется сначала просмотреть весь блог, все понять, а затем попробовать написать самостоятельно, используя мой код в качестве ссылки.

В этом посте я расскажу:

  1. Маркеры и обнаружение Aruco
  2. Перспективные преобразования
  3. Дополнение объекта к нашей реальности
  4. Возможные улучшения

Маркеры Aruco

Как вы можете видеть на видео, вырез в моей руке с маленькими черными и белыми квадратами - это маркер Aruco. Это будет моя целевая поверхность. Помещая маркер, я могу контролировать местоположение и движение лисы.

Если вы внимательно посмотрите на один маркер, вы увидите, что есть 64 подквадрата (8 на 8), которые окрашены в черный или белый цвет. Картина не совсем случайна. Дизайн пытается гарантировать, что маркер не будет ошибочно принят за какой-либо элемент фона и наоборот. По той же причине мы не стали бы использовать простую шахматную доску в качестве маркера aruco. Я решил использовать маркеры Aruco в качестве целевой поверхности, потому что их простой черно-белый узор упрощает их обнаружение и идентификацию.

Итак, учитывая исходный узор aruco, как мне найти его на моем изображении?

Мы находим все контуры на исходном изображении (Контур - это просто граница объекта на изображении). Здесь я напрямую использовал функцию cv2.findContours, но в задней части она может делать что-то столь же простое, как поиск краев, а затем попытки соединить их и получить замкнутые фигуры.

Затем функция cv2.approxPolyDP () использует алгоритм Дугласа Пекера для сглаживания контуров.

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

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

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

Ура!! На изображении мы нашли маркер aruco.

Гомография и преобразование перспективы

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

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

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

Мировая система координат (WCS) - это трехмерная декартова система координат, в которой мы описываем наш интересующий объект. Он может храниться в произвольном порядке по нашему усмотрению. Система координат камеры (CCS) также является трехмерной декартовой системой координат, оси которой соответствуют ориентации камеры.

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

Затем у нас есть внутренняя матрица (A), которая представляет собой проекцию из координат трехмерной камеры (X, Y, Z) на координаты 2d пикселей (u, v). Достаточно знать, что внутренняя матрица зависит исключительно от камеры, а не от ее ориентации или чего-то еще. Он заботится о фокусном расстоянии камеры, соотношении сторон и т. Д. На данный момент, допустим, у нас есть встроенная матрица.

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

До сих пор мы располагали маркер Aruco на изображении. Используя его углы, мы получаем четыре соответствия (пара (P, P *), где P находится в WCS, а P * - соответствующая точка в пиксельных координатах) . Если мы попытаемся найти параметры, достаточно 4 баллов, чтобы найти гомографию.

Итак, что такое гомография? Гомография - это вырожденная форма уравнения перспективы. Используя гомографию H, мы можем преобразовывать точки, принадлежащие определенной плоской поверхности; в данном случае плоскость W = 0. Обратите внимание, что в нашем уравнении перспективы для всех 4 точек на маркере компонент z (W) равен 0, и поэтому мы не можем получить никакой информации о r3. Но мы знаем, что r3 должно быть перекрестным произведением r1 и r2 (ортогональные оси). Используя это, мы находим r3 в функции extended_RT.

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

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

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

Учитывая эти образцы изображений, он находит коэффициент искажения вместе с собственной матрицей (наша цель).

Проблема здесь в том, что шахматную доску нужно делать много снимков.

Если вы ленивы, то есть другой способ. Вы можете попытаться приблизить это с умом. Матрица имеет вид

c x и c y должны составлять половину разрешения веб-камеры. Так что для меня разрешение было 1280x640, что дает c x = 640 и c y = 320. Фокусное расстояние можно приблизительно определить после этого сообщения. Точное значение f не имеет решающего значения для этого приложения, и поэтому умное предположение может сработать.

Итак, после всех этих хлопот у нас есть матрица преобразования перспективы.

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

Рендеринг

Я получил лису с сайта clara.io, где есть большой выбор 3D-объектов, из которых вы можете выбирать. Мы будем иметь дело с форматом .obj. Это очень простой способ описания трехмерного объекта. Все, что нам нужно знать, это то, что в нем перечислены все координаты вершин, координаты текстуры и информация о лицах.

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

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

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

Совет. При работе с изображениями в OpenCV в Python позаботьтесь о координатах и ​​расположении пикселей на изображении. Я хочу сказать, что интенсивность в точке (x, y) изображения равна img [y] [x], а не img [x] [y]. Такие ошибки тратят много времени и очень неприятны.

Например, на этом изображении 100x100 круг нарисован в точке (20,50), но значение пикселя в изображении [20] [50] является черным, а изображение [50] [20] - красным

Резюме

Вот как все это сложится -

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

На каждом временном шаге мы получаем кадр с веб-камеры. Мы пытаемся найти маркер aruco в кадре, находя все контуры, отфильтровывая четырехугольники и затем сопоставляя их битовые сигнатуры. Если мы находим маркер aruco в нашем кадре, мы используем его углы для оценки гомографии от мировых координат до пиксельных координат. Эта гомография расширена, чтобы получить полную матрицу перспективы. Мы смещаем вершины нашего объекта к центру маркера и, используя перспективное преобразование, находим его 2D-проекцию на нашем изображении.

Дальше

Одно из основных улучшений, над которым я сейчас работаю, - это не обнаруживать маркер каждый раз, а отслеживать его. Я хочу сказать, что если я знаю, что маркер в данный момент находился в некоторой позиции, то я могу использовать эту информацию, когда буду искать ее на следующем временном шаге, вместо того, чтобы искать ее заново с нуля. Именно это и есть отслеживание. Это решит проблему нестабильности видео, которое у нас есть прямо сейчас, и, поскольку для этого потребуется меньше обработки, моделирование будет более отзывчивым. Использование алгоритма Лукаса-Канде для разреженного оптического потока должно решить нашу проблему, и я планирую рассказать об этом в следующей части.

Некоторые другие проблемы, которые я хотел бы решить, - это сделать рендеринг более реалистичным.

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

Я хотел бы поблагодарить Хуана Галлостру Ацина, чей блог действительно помог мне начать работу над этим проектом и помог написать мою первую версию. Он использовал дескрипторы SIFT для сопоставления признаков и оценки гомографии. Вам тоже стоит заглянуть в его блог.

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

Ссылки

  1. Блог Хуана Галлостры Ацина
  2. Алгоритм Дугласа Пекера
  3. Описание файла .obj
  4. 3D лиса использовала
  5. Репозиторий GitHub
  6. Отображение УФ-текстуры
  7. Исходное изображение шахматной доски
  8. Примерное фокусное расстояние камеры

PS: Я впервые делаю учебник. Если вы обнаружили какую-либо часть неясной или неправильной, не стесняйтесь оставлять комментарии или писать мне на [email protected], чтобы я мог улучшить эти сообщения. Спасибо.