Стабилизация изображения с камеры на Android NDK (C)

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

Запросить поддержку EIS и включить EIS

Чтобы включить EIS, настройте свой сеанс на использование AR_IMAGE_STABILIZATION_MODE_EIS . Если устройство не поддерживает функцию EIS, это приведет к выдаче исключения из ARCore.

int enableEis = 0;
ArSession_isImageStabilizationModeSupported(
    ar_session, AR_IMAGE_STABILIZATION_MODE_EIS, &enableEis);
if (!enableEis) {
  return;
}
// Create a session config.
ArConfig* ar_config = NULL;
ArConfig_create(ar_session, &ar_config);

// Enable Electronic Image Stabilization.
ArConfig_setImageStabilizationMode(ar_session, ar_config, AR_IMAGE_STABILIZATION_MODE_EIS);
CHECK(ArSession_configure(ar_session, ar_config) == AR_SUCCESS);

// Release config resources.
ArConfig_destroy(ar_config);

Преобразование координат

Когда EIS включен, средству визуализации необходимо использовать измененные координаты устройства и соответствующие координаты текстуры, которые включают компенсацию EIS при рендеринге фона камеры. Чтобы получить координаты, компенсированные EIS, используйте ArFrame_transformCoordinates3d , используя AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES в качестве входных данных и AR_COORDINATES_3D_EIS_NORMALIZED_DEVICE_COORDINATES в качестве выходных данных, чтобы получить координаты 3D-устройства и AR_COORDINATES_3D_EIS_TEXTURE_NORMALIZED _TEXTURE_NORMALIZED в качестве вывода для получения координат 3D-текстуры. На данный момент единственным поддерживаемым типом входных координат для ArFrame_transformCoordinates3d является AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES .

int kNumVertices = 4;
// Positions of the quad vertices in clip space (X, Y).
const GLfloat kVertices[] = {
    -1.0f, -1.0f, +1.0f, -1.0f, -1.0f, +1.0f, +1.0f, +1.0f,
};
float transformed_vertices_[4 * 3];
float transformed_uvs_[4 * 3];

ArFrame_transformCoordinates3d(
    session, frame, AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES,
    kNumVertices, kVertices,
    AR_COORDINATES_3D_EIS_NORMALIZED_DEVICE_COORDINATES,
    transformed_vertices_);
ArFrame_transformCoordinates3d(
    session, frame, AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES,
    kNumVertices, kVertices, AR_COORDINATES_3D_EIS_TEXTURE_NORMALIZED,
    transformed_uvs_);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, camera_texture_id_);
glUseProgram(camera_program_);
glUniform1i(camera_texture_uniform_, 0);

// Set the vertex positions and texture coordinates.
glVertexAttribPointer(camera_position_attrib_, 3, GL_FLOAT, false, 0,
                      transformed_vertices_);
glVertexAttribPointer(camera_tex_coord_attrib_, 3, GL_FLOAT, false, 0,
                      transformed_uvs_);
glEnableVertexAttribArray(camera_position_attrib_);
glEnableVertexAttribArray(camera_tex_coord_attrib_);

Когда EIS выключен, выходные 3D-координаты эквивалентны своим 2D-аналогам, при этом значения z не вызывают изменений.

Изменить шейдеры

Рассчитанные 3D-координаты должны быть переданы в шейдеры фонового рендеринга. Буферы вершин теперь трехмерные с EIS:

layout(location = 0) in vec4 a_Position;
layout(location = 1) in vec3 a_CameraTexCoord;
out vec3 v_CameraTexCoord;
void main() {
  gl_Position = a_Position;
  v_CameraTexCoord = a_CameraTexCoord;
}

Кроме того, фрагментный шейдер должен применить коррекцию перспективы:

precision mediump float;
uniform samplerExternalOES u_CameraColorTexture;
in vec3 v_CameraTexCoord;
layout(location = 0) out vec4 o_FragColor;
void main() {
  vec3 tc = (v_CameraTexCoord / v_CameraTexCoord.z);
  o_FragColor = texture(u_CameraColorTexture, tc.xy);
}

Дополнительные сведения см. в примере приложения hello_eis_kotlin .