Дополненная реальность с маркерами ArUco в OpenCV

Здесь вы узнаете, что такое маркеры ArUco и зачем они нужны в задачах дополненной реальности с использованием OpenCV.

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

Что есть маркеры ArUco?

Первое сообщение о маркерах ArUco появилось в 2014 году в работе S.Garrido-Jurado с соавторами «Automatic generation and detection of highly reliable fiducial markers under occlusion», что на русском звучит как «Автоматическая генерация и высоконадежное обнаружение фидуциальных маркеров при окклюзии». О, как! Сразу несколько непонятных слов. Окклюзия (англ. occlusion от лат. occlusio «сокрытие») — термин, который указывает на какое-либо состояние, которое обычно открыто, а в определённый момент времени полностью закрыто. Фидуциальный маркер или фидуциал — это объект, помещенный в поле зрения системы визуализации, который появляется в полученном изображении, для использования в качестве точки отсчета или меры. Это может быть либо что-то, помещенное в/или на предмет изображения, либо метка или набор меток в сетке оптического прибора. ArUco расшифровывается как Augmented Reality University of Cordoba (Университет дополненной реальности в Кордове). Вот где он был разработан, в Испании. Ниже вы видите примеры маркеров ArUco.

Примеры маркеров ArUco
Примеры маркеров ArUco

Маркер ArUco — это фидуциальный маркер, который размещается на изображаемом объекте или сцене. Он представляет собой чёрный квадрат с ярко выраженными границами, внутри которого располагается белый узор, однозначно его идентифицирующий. Черная граница облегчает его обнаружение. Маркеры могут быть созданы разных размеров. Размер выбирается в зависимости от размера объекта или сцены для надёжного обнаружения. Если очень маленькие маркеры не обнаруживаются, то простое увеличение их размера позволит их обнаружить.

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

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

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

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

Создание маркеров ArUco в OpenCV

Используя OpenCV можно легко генерировать эти маркеры. Модуль aruco в OpenCV имеет в общей сложности 25 словарей предопределенных маркеров. Все маркеры в словарях содержат одинаковое количество блоков или битов (4×4, 5×5, 6×6 или 7×7) и каждый словарь содержит фиксированное количество маркеров (50, 100, 250 или 1000). Ниже мы покажем, как генерировать и обнаруживать различные виды маркеров aruco в Python.

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

Вызов функции getPredefinedDictionary, которая загружает словарь из 250 маркеров, где каждый маркер содержит шаблон 6×6 бит показан ниже.

import cv2 as cv
import numpy as np

# Загрузить предопределенный словарь
dictionary = cv.aruco.Dictionary_get(cv.aruco.DICT_6X6_250)

# Сгенерировать маркер
markerImage = np.zeros((200, 200), dtype=np.uint8)
markerImage = cv.aruco.drawMarker(dictionary, 33, 200, markerImage, 1);

cv.imwrite("marker33.png", markerImage);

Приведенная выше функция drawMarker позволяет выбрать маркер с заданным идентификатором (второй параметр – 33) из набора 250 маркеров, имеющих идентификаторы от 0 до 249. Третий параметр функции drawMarker определяет размер сгенерированного маркера. В приведенном выше примере он будет генерировать изображение с размером 200×200 пикселей. Четвертый параметр представляет объект, в котором будет храниться сгенерированный маркер (markerImage). Наконец, пятый параметр является параметром толщины и решает, сколько блоков должно быть добавлено в качестве границы сгенерированного двоичного шаблона. В приведенном выше примере вокруг сгенерированного шаблона размером 6×6 будет добавлена граница шириной 1 бит, что задает размер блока 7×7 бит в изображении размером 200×200 пикселей. Сгенерированный с помощью указанного выше кода маркер будет выглядеть так:

Один из маркеров шаблона
Один из маркеров шаблона

Для большинства приложений необходимо создавать несколько маркеров и размещать их в сцене.

Обнаружение маркеров Aruco

После размещения маркеров ArUco в сцене их надо обнаружить и использовать для дальнейшей обработки. Ниже показано, как найти маркеры.

# Загрузить словарь, который использовался для создания маркеров.
dictionary = cv.aruco.Dictionary_get(cv.aruco.DICT_6X6_250)

# Инициализировать параметры детектора, используя значения по умолчанию
parameters =  cv.aruco.DetectorParameters_create()

# Обнаружение маркеров на изображении
markerCorners, markerIds, rejectedCandidates = cv.aruco.detectMarkers(frame, dictionary, parameters=parameters)

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

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

Для каждого успешно обнаруженного маркера, вычисляются четыре угловые точки в следующем порядке верхняя левая, верхняя правая, нижняя правая и нижняя левая, по часовой стрелке, начиная с верхней левой. Именно в таком порядке они хранятся в массиве Numpy.

Функция detectMarkers используется для обнаружения и определения местоположения углов маркеров. Первый параметр — это изображение сцены с маркерами. Второй параметр — словарь, используемый для генерации маркеров. Успешно обнаруженные маркеры будут сохранены, в markerCorners, а их идентификаторы в markerIds. Объект DetectorParameters, инициализированный ранее, также передается в качестве параметра. Наконец, отклоненные кандидаты на маркеры сохраняются внутри rejectedCandidates.

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

Приложение дополненной реальности

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

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

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

Обнаружение маркеров на изображении
Обнаружение маркеров на изображении

Четыре соответствующих набора точек на входном изображении и новое изображение сцены используются для вычисления гомографии. Гомография. Что это? О том, что такое гомографию можно прочитать здесь. Учитывая то, что homography — это преобразование, которое отображает одну соответствующую точку в другую, мы можем получать сцены с разных ракурсов.

Гомография
Гомография

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

# Рассчитать гомографию
h, status = cv.findHomography(pts_src, pts_dst)
        
# Деформация исходного изображения к месту назначения на основе гомографии
warped_image = cv.warpPerspective(im_src, h, (frame.shape[1],frame.shape[0]))
        
# Подготовьте маску, представляющую область для копирования из деформированного изображения в исходный кадр.
mask = np.zeros([frame.shape[0], frame.shape[1]], dtype=np.uint8);
cv.fillConvexPoly(mask, np.int32([pts_dst_m]), (255, 255, 255), cv.LINE_AA);

# Размыть маску, чтобы не копировать граничные эффекты из деформации
element = cv.getStructuringElement(cv.MORPH_RECT, (3,3));
mask = cv.erode(mask, element, iterations=3);

# Скопируйте маску на 3 канала.
warped_image = warped_image.astype(float)
mask3 = np.zeros_like(warped_image)
for i in range(0, 3):
    mask3[:,:,i] = mask/255

# Скопируйте искаженное изображение в маске в исходный кадр в области маски.
warped_image_masked = cv.multiply(warped_image, mask3)
frame_masked = cv.multiply(frame.astype(float), 1-mask3)
im_out = cv.add(warped_image_masked, frame_masked)

Мы используем новые угловые точки изображения сцены в качестве исходных точек (pts_src) и соответствующие угловые точки изображения внутри рамки изображения в нашем захваченном изображении в качестве точек назначения (dst_src) , Функция OpenCV findHomography вычисляет функцию гомографии h между исходной и целевой точками. Матрица гомографии затем используется для деформации нового изображения, чтобы поместиться в целевой кадр. Деформированное изображение маскируется и копируется в целевой кадр. В случае видео этот процесс повторяется на каждом кадре.

Рекомендации

OpenCV Documentation on ArUco markers

Automatic generation and detection of highly reliable fiducial markers under occlusion

Aruco project at Sourceforge

Pixabay Images/Videos: [1], [2], [3], [4]

По мотивам Augmented Reality using ArUco Markers in OpenCV (C++ / Python)

CC BY-NC 4.0 Дополненная реальность с маркерами ArUco в OpenCV, опубликовано К ВВ, лицензия — Creative Commons Attribution-NonCommercial 4.0 International.


Респект и уважуха

Добавить комментарий