Menstabilkan gambar kamera di Android NDK (C)

ARCore kini mendukung Electronic Image Stabilization (EIS), yang membantu menghasilkan pratinjau kamera yang lancar. EIS mencapai stabilisasi dengan mengamati gerakan ponsel menggunakan giroskop dan menerapkan mesh homoografi kompensasi dalam batas tekstur kamera yang melawan guncangan kecil. EIS hanya didukung dalam orientasi potret perangkat. Semua orientasi akan didukung dalam ARCore rilis 1.39.0.

Meminta dukungan EIS dan mengaktifkan EIS

Untuk mengaktifkan EIS, konfigurasi sesi Anda agar menggunakan AR_IMAGE_STABILIZATION_MODE_EIS. Jika perangkat tidak mendukung fitur EIS, hal ini akan menyebabkan pengecualian ditampilkan dari 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);

Mentransformasi koordinat

Saat EIS aktif, perender perlu menggunakan koordinat perangkat yang telah dimodifikasi dan koordinat tekstur yang cocok yang menyertakan kompensasi EIS saat merender latar belakang kamera. Untuk mendapatkan koordinat EIS yang dikompensasi, gunakan ArFrame_transformCoordinates3d, menggunakan AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES sebagai input dan AR_COORDINATES_3D_EIS_NORMALIZED_DEVICE_COORDINATES sebagai output untuk mendapatkan koordinat perangkat 3D, dan AR_COORDINATES_3D_EIS_TEXTURE_NORMALIZED sebagai output untuk mendapatkan koordinat tekstur 3D. Untuk saat ini, satu-satunya jenis koordinat input yang didukung untuk ArFrame_transformCoordinates3d adalah 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_);

Jika EIS nonaktif, koordinat 3D output setara dengan koordinat 2D, dengan nilai z yang disetel agar tidak ada perubahan.

Mengubah shader

Koordinat 3D yang dihitung harus diteruskan ke shader rendering latar belakang. Buffer verteks sekarang menjadi 3D dengan 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;
}

Selain itu, shader fragmen perlu menerapkan koreksi perspektif:

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

Lihat aplikasi contoh hello_eis_kotlin untuk detail selengkapnya.