Stabilizzare le immagini della fotocamera su Android NDK (C)

ARCore ora supporta la stabilizzazione elettronica delle immagini (EIS), che consente di produrre un'anteprima fluida della fotocamera. La tecnologia EIS raggiunge la stabilizzazione osservando il movimento del telefono tramite il giroscopio e applicando una rete omiciale di compensazione entro i limiti della texture della fotocamera per contrastare le piccole scosse. EIS è supportato solo con l'orientamento verticale del dispositivo. Tutti gli orientamenti saranno supportati nella versione 1.39.0 di ARCore.

Esegui una query per il supporto EIS e abilita EIS

Per abilitare EIS, configura la sessione in modo che utilizzi AR_IMAGE_STABILIZATION_MODE_EIS. Se il dispositivo non supporta la funzionalità EIS, verrà generata un'eccezione da 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);

Trasforma le coordinate

Quando la funzionalità EIS è attiva, il renderer deve utilizzare le coordinate del dispositivo modificate e le coordinate della texture corrispondenti che incorporano la compensazione EIS durante il rendering dello sfondo della fotocamera. Per ottenere le coordinate EIS con compensazione, utilizza ArFrame_transformCoordinates3d, utilizzando AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES come input e AR_COORDINATES_3D_EIS_NORMALIZED_DEVICE_COORDINATES come output per ottenere le coordinate 3D del dispositivo e AR_COORDINATES_3D_EIS_TEXTURE_NORMALIZED come output per ottenere le coordinate della texture 3D. Al momento, l'unico tipo di coordinata di input supportato per 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_);

Quando EIS è disattivato, le coordinate 3D di output sono equivalenti alle rispettive controparti 2D, con valori z impostati per non produrre modifiche.

Modificare gli sudamericani

Le coordinate 3D calcolate devono essere trasmesse agli mesh di rendering dello sfondo. I buffer del vertice sono ora in 3D con 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;
}

Inoltre, lo strumento di protezione dei frammenti deve applicare la correzione prospettica:

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

Per ulteriori dettagli, vedi l'app di esempio hello_eis_kotlin.