Использование EasyAR в 3D-движках
Для использования EasyAR в 3D-движке требуется отрисовка изображения с камеры и виртуальных объектов. Для совмещения виртуальных объектов с изображением камеры необходимо учитывать возможное несоответствие параметров при генерации и отображении изображения, таких как положение, ориентация, формат кадра, соотношение сторон физической камеры и экрана. При интеграции EasyAR в 3D-движок без встроенной поддержки необходимо уделить особое внимание следующим деталям.
Обрезка заполнения границ изображения камеры
Обрезка, транспонирование и кодирование изображения требуют значительных вычислительных ресурсов. Для уменьшения вычислений и задержек обычно используются более "сырые" форматы. Для удобства кодирования видео изображение с физической камеры часто выравнивается по блокам 8x8, 16x16, 32x32, 64x64. Например, на некоторых телефонах при выборе разрешения 1920x1080 выходное изображение может стать 1920x1088, потому что 1080 не кратно 64.

Это требует удаления этих избыточных заполняющих областей при рендеринге. Существует несколько возможных подходов: один - указать ширину при загрузке изображения в видеопамять (например, в OpenGL можно использовать glPixelStorei(GL_PACK_ROW_LENGTH, ...)); другой - вручную вычислять UV-координаты во фрагментном шейдере и обрезать избыточные части при сэмплировании изображения.
Рендеринг с учетом ориентации экрана
На мобильных устройствах изображение с физической камеры обычно фиксировано относительно корпуса устройства и не меняется при изменении ориентации экрана. Однако изменение ориентации корпуса телефона влияет на наше определение направлений "верх", "низ", "лево", "право" на изображении. При рендеринге текущая ориентация экрана также влияет на ориентацию отображаемого изображения.
Обычно при рендеринге необходимо определить угол поворота изображения камеры относительно ориентации экрана.
Пусть \(\theta_{screen}\) обозначает угол в радианах, на который изображение экрана повернуто по часовой стрелке относительно естественной (нативной) ориентации экрана. Пусть \(\theta_{phycam}\) обозначает угол в радианах, на который изображение физической камеры нужно повернуть по часовой стрелке для правильного отображения на экране в естественной ориентации. Тогда \(\theta\) - угол в радианах, на который изображение физической камеры нужно повернуть по часовой стрелке для отображения на текущем экране.
Для задней камеры:
Например, на Android-телефоне, при использовании в естественной ориентации, \(\theta_{screen} = 0, \theta_{phycam} = \frac{\pi}{2}\), тогда \(\theta = \frac{\pi}{2}\).
Для передней камеры, если после поворота выполняется зеркальное отражение по горизонтали (flip), то:
Примечание
При изменении ориентации экрана необходимо немедленно пересчитать \(\theta\) на первом же кадре после поворота, иначе может возникнуть кратковременное неправильное отображение ориентации изображения.
Рендеринг фона камеры и виртуальных объектов
Для совмещения виртуальных объектов с изображением камеры на мобильных устройствах необходимо разместить и камеру рендеринга, и объекты в виртуальном пространстве, полностью соответствующем реальному, и использовать для рендеринга те же углы обзора (FOV) и соотношение сторон, что и у физической камеры. Перспективная проекция, через которую проходит изображение камеры и виртуальные объекты, практически идентична, с одним ключевым отличием: большая часть преобразования для изображения камеры происходит в физической камере, в то время как преобразование для виртуальных объектов является полностью вычислительным процессом.
Далее используется соглашение OpenGL. Предположим, что система координат камеры определена так: ось X направлена вправо, ось Y направлена вверх, ось Z направлена из экрана наружу. Система координат отсечения (clip space) определена так: ось X направлена вправо, ось Y направлена вверх, ось Z направлена из экрана наружу, ось W - виртуальная ось.
В этом случае, матрица перспективной проекции, необходимая для рендеринга изображения камеры, выглядит следующим образом:
Где:
flip- флаг отражения изображения по горизонтали (1 - отражено, 0 - не отражено).- \(\theta\) - угол поворота изображения по часовой стрелке (в радианах).
- \(s_x\), \(s_y\) - коэффициенты масштабирования, используемые для равномерного масштабирования или заполнения (padding). Они зависят от \(\theta\).
Эта матрица преобразования сначала масштабирует изображение камеры, затем поворачивает его и, наконец, отражает (если flip = 1). Для рендеринга следует использовать прямоугольник, покрывающий весь экран. Например, в OpenGL вершины прямоугольника можно разместить в точках \((-1, -1, 0)\), \((1, -1, 0)\), \((1, 1, 0)\), \((-1, 1, 0)\), установить UV-координаты в соответствующих углах и использовать данную матрицу перспективной проекции для рендеринга.
Матрица перспективной проекции, необходимая для рендеринга виртуальных объектов, выглядит следующим образом:
Где:
- \(n\), \(f\) - параметры ближней (near) и дальней (far) плоскостей отсечения, используемые в стандартной матрице перспективной проекции для 3D-рендеринга.
- \(w\), \(h\) - ширина и высота изображения камеры в пикселях.
- \(f_x\), \(f_y\), \(c_x\), \(c_y\) - внутренние параметры камеры (intrinsics), где \(f_x\), \(f_y\) - фокусные расстояния в пикселях, \(c_x\), \(c_y\) - положение главной точки (principal point) в пикселях.
Эта матрица проекции последовательно выполняет следующие преобразования:
- Перспективное преобразование внутренних параметров камеры (с учетом того, что направление осей Y и Z в системе координат изображения OpenCV противоположно направлению осей в системе координат камеры OpenGL, выполняется двойное преобразование систем координат).
- Преобразование из системы координат пикселей изображения в систему координат прямоугольника изображения.
- Преобразование для учета ближней и дальней плоскостей отсечения.
- Преобразование перспективной проекции, используемое при рендеринге изображения камеры.
После упрощения получаем:
Из вышеизложенного следует, что рендеринг обычно выполняется в два прохода: сначала рендерится изображение камеры (фон), затем поверх него рендерятся виртуальные объекты.
В некоторых 3D-движках матрица перспективной проекции выражается через параметры, такие как горизонтальный угол обзора (FOV) и соотношение сторон. Если пренебречь поворотом, отражением и смещением главной точки, то эти параметры можно вычислить: горизонтальный угол обзора \(\alpha=2 \arctan{\frac{w}{2 f_x}}\), соотношение сторон \(r=\frac{w}{h}\).
Важно отметить, что в этом процессе не учитывается дисторсия камеры, так как в настоящее время дисторсия камер на большинстве мобильных телефонов очень незначительна.