Stabiliser les images de l'appareil photo sur le NDK Android (C)

ARCore est désormais compatible avec la stabilisation d'image électronique (EIS), qui permet de générer un aperçu de l'appareil photo fluide. L'EIS obtient une stabilisation en observant les mouvements du téléphone à l'aide d'un gyroscope et en appliquant un maillage d'homographie de compensation dans les limites de la texture de l'appareil photo qui compense les légers tremblements. L'EIS n'est compatible qu'avec l'orientation portrait de l'appareil. Toutes les orientations seront compatibles avec la version 1.39.0 d'ARCore.

Requête pour prendre en charge l'EIS et activer l'EIS

Pour activer l'EIS, configurez votre session de manière à utiliser AR_IMAGE_STABILIZATION_MODE_EIS. Si l'appareil n'est pas compatible avec la fonctionnalité EIS, une exception sera générée à partir d'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);

Transformer des coordonnées

Lorsque l'EIS est activé, le moteur de rendu doit utiliser les coordonnées modifiées de l'appareil et les coordonnées de texture correspondantes qui intègrent la compensation EIS lors du rendu de l'arrière-plan de l'appareil photo. Pour obtenir les coordonnées EIS comparées, utilisez ArFrame_transformCoordinates3d, en utilisant AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES comme entrée et AR_COORDINATES_3D_EIS_NORMALIZED_DEVICE_COORDINATES en tant que sortie pour obtenir les coordonnées 3D de l'appareil et AR_COORDINATES_3D_EIS_TEXTURE_NORMALIZED en sortie pour obtenir les coordonnées de texture 3D. Pour le moment, le seul type de coordonnée d'entrée accepté pour ArFrame_transformCoordinates3d est 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_);

Lorsque l'EIS est désactivé, les coordonnées 3D de sortie sont équivalentes à celles de leurs équivalents 2D, les valeurs z étant définies pour ne générer aucune modification.

Modifier les nuanceurs

Les coordonnées 3D calculées doivent être transmises aux nuanceurs de rendu d'arrière-plan. Les tampons de sommet sont maintenant en 3D avec 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;
}

De plus, le nuanceur de fragments doit appliquer la correction de la perspective:

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);
}

Pour en savoir plus, consultez l'application exemple hello_eis_kotlin.