28 августа 2015 г.

Как подключить MarkersDetector.dll в проект Unreal Engine 4

В этом посте описана инструкция, как можно подключить мою библиотеку MarkersDetector.dll, которая использует несколько вызовов библиотеки OpenCV. Мне пришлось собрать свою dll, а не использовать OpenCV напрямую, из-за особенности сборщика мусора в UE4 - он крашился при вызове некоторых нужных методов, например, cv::findContours(). В MarkersDetector.dll упакован необходимый минимум, чтобы получать в реальном времени координаты и вектор поворота веб-камеры относительно статичных маркеров.


Предполагается, что у вас настроена и работает связка UE 4.8.3 (4.9) и VS 2013 на Win64. А также скачены файлы MarkersDetector.h, MarkersDetectorDll.dll, MarkersDetecorDll.lib, WebcamReader.h, WebcamReader.cpp и header-файлы opencv: ссылка на архив.

Update: готовый настроенный проект под UE 4.9 можно скачать здесь.
Посмотреть исходники MarkersDetector, готовые для билда под Android, можно на Github.

Шаг 1. Создать проект в UE4

Шаг необязательный. Интегрировать MarkersDetector можно и в ранее созданный проект.
Для нового проекта запускаем UE4, выбираем пункт меню для создания нового C++ проекта. Шаблон для проекта может быть любой. После создания открываем VS, пробуем собрать и запустить оттуда новый проект. Если всё хорошо, двигаемся дальше.

Шаг 2. Добавить зависимости в проект

В корневой директории проекта создаем новую папку ThirdParty, в ней создаем папку MarkersDetector, в ней две папки Includes и Win64. В папку Includes помещаем мой MarkersDetector.h и папку opencv2, в Win64 - MarkersDetector.lib:
ThirdParty/MarkersDetector/Includes/MarkersDetector.h
ThirdParty/MarkersDetector/Includes/opencv2/*
ThirdParty/MarkersDetector/Win64/MarkersDetectorDll.lib

Теперь нужно подключить эти файлы в проект.  Находим файл Source/%имя_проекта%/%имя_проекта%.build.cs и добавляем.
В начало:
using System.IO;

В конструктор:
string ModulePath = Path.GetDirectoryName(RulesCompiler.GetModuleFilename(this.GetType().Name));
string ThirdPartyPath = Path.GetFullPath(Path.Combine(ModulePath, "../../ThirdParty/"));

PublicAdditionalLibraries.Add(Path.Combine(ThirdPartyPath, "MarkersDetector/Win64/MarkersDetectorDll.lib"));
PublicIncludePaths.Add(Path.Combine(ThirdPartyPath, "MarkersDetector/Includes"));

В PublicDependencyModuleNames:
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "RHI", "RenderCore", "ShaderCore" });
Теперь нужно добавить MarkersDetectorDll.dll в папку, где находится собранный исполняемый файл проекта: x64/Release/. Если после успешной сборки на этапе запуска редактора будет ругаться, то значит, dll лежит не там.
Стоит попробовать собрать проект. Если успешно, то можно идти дальше.

Шаг 3. Добавить класс WebcamReader, от которого будет создан Blueprint

При выключенном редакторе скопировать файлы WebcamReader.h и WebcamReader.cpp в папку с проектом. Добавить их в проект в VS. Для этого можно снова скопировать эти файлы, но уже из папки с проектом и вставить в самом Project Explorer в VS.
WebcamReader.h подключает Markers.Detector.h, поэтому теперь все зависимости будут использованы. В WebcamReader.cpp изменить первый include на соответствующий имени вашего проекта.
Теперь обязательно нужно собрать проект и запустить.

Шаг 4. Добавить Blueprint, основанный на WebcamReader.

В запущенном UE4-редакторе вашего проекта в списке C++ Classes должен обнаружится WebCamReader. Выберите его и, используя правую клавиши мыши, вызовите контекстное меню. Там должен быть пункт для создания Blueprint на основе этого класса - выберите это. Можете назвать файл BP_WebCamReader. Имя неважно.
Теперь этот BP нужно настроить: добавить меш, мешу материал, материалу текстуру как параметр, который и будет обновляться при получении кадров из камеры. Обновление вызывает BP-event OnNextVideoFrame. Его будем задействовать.

Для начала нужно создать материал, назовем его M_Webcam, открыть, в редакторе создать ноду TextureAsParam2D от пина Emissive Color материала. Параметр переименовать в Texture (через имя этого параметра будет обновление значения). В качестве UV этой текстуры можно выбрать любую текстуру по умолчанию. После этого сохранить материал и закрыть.

Теперь нужно вернуться к созданному ранее BP. Зайти в него и добавить любой меш: куб или плоскость. Нужно дать переменную этому мешу. Пусть будет Billboard. Теперь нужно перейти в основной редактор BP Event Graph и от ноды Even Begin Play создать ноду Create Dynamic Material Instance. В качестве таргет указать наш меш, а в качестве Source Material выбрать ранее созданный нами материал M_Webcam. Теперь нужно создать переменную типа Dynamic Material Instance и назвать её DynamicMaterial. От созданной ноды из Return Value вытянуть и создать ноду Set DynamicMaterial, то есть присвоить значение переменной DynamicMaterial экземпляр нашего динамического материала. Теперь этот же результат (экземпляр динамического материала) нужно присвоить мешу через ноду SetMaterial.

Теперь нужно настроить обновление текстуры. Из ноды Event OnNextVideoFrame вытянуть и создать ноду Set Texture Parameter Value, в Target указать созданную нами переменную DynamicMaterial, в Parameter Name вписать "Texture" и Value указать Video Texture - это внутрення переменная BP, получаемая из класса WebCamReader.

В итоге Event Graph должен быть таким, как на изображении

После этого нужно поместить экземпляр нашего BP на сцену. В нём можно настроить некоторые параметры, например, размер видео и индекс устройства камеры. Можно попробовать запустить, нажав кнопку Play - вместо текстуры куба должен быть видео поток с веб-камеры.

Шаг 5. Получение вектора местоположения и поворота камеры

После обновления текстуры данные местоположения и поворота находятся в двух переменных, доступных из BP: CameraLocation и CameraRotation. Используя Event Graph, их значения можно назначать различным объектам или хотя бы выводить на экран.

Калибровка камеры и настройка местоположения маркеров

Необходимые утилиты находятся в отдельном архиве.

Нужно использовать Calibration.exe для запуска процедуры калибровки камеры. При калибровке используются изображения шахматной доски. Можно использовать фото, записанное видео или прямой видео поток с камеры. Утилита при запуске описывает параметры запуска. Для быстрого запуска калибровки с видео-потока веб-камеры можно запустить calibration.bat. При успешной калибровке будет создан файл camera.yml, в котором можно найти значения двух матриц: camera_matrix и distortion_coefficients. Их значения следует внести в код WebcamReader.cpp в соответствующие переменные в конструктор.

Так как MarkersDetector определяет местоположение камеры по маркерам, то нужно заранее указывать id маркера и его местоположение относительно системы координат помещения.
Для генерации изображения маркера по коду Хемминга следует использовать утилиту MakeMarker.exe. Первым аргументом указывается id маркера: от 0000000000 до 1111111111. Второй аргумент необязательный - это имя файла, в котором будет записано изображение маркера (по умолчанию равен id маркера). Id можно выбирать не по порядку. Количество маркеров, которое нужно напечатать, зависит от помещения. Для тестирования достаточно хотя бы одного. Полученные изображения маркеров следует распечатать на листе так, чтобы каждый маркер на своем листе остался квадратным. Длина стороны квадрата у всех маркеров должна быть одинаковой.

Распечатанные маркеры нужно разместить в помещении и записать их координаты в системе координат этого помещения, например, от угла. Единицу измерения можно использовать любую, например, сантиметры. Координаты маркеров следует внести в код программы в WebcamReader.cpp в переменную markersLocations в формате id: loc. По аналогии с уже записанными. Ведущие нули у id не записываются. Следует так же обратить внимание на значение переменной markerHalfSize. В коде оно указано 10. Это половина ширины квадрата вашего напечатанного маркера в той же единицы измерения, что использовалась для записи местоположения маркеров.



Видео со сборкой проекта под Windows и Android

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



Комментариев нет:

Отправить комментарий