Menstabilkan gambar kamera di Android NDK (C)

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

Mengkueri dukungan EIS dan mengaktifkan EIS

Untuk mengaktifkan EIS, konfigurasikan sesi Anda untuk menggunakan AR_IMAGE_STABILIZATION_MODE_EIS. Jika perangkat tidak mendukung fitur EIS, 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 harus menggunakan koordinat perangkat yang dimodifikasi dan koordinat tekstur yang cocok yang menggabungkan kompensasi EIS saat merender latar belakang kamera. Untuk mendapatkan koordinat kompensasi EIS, 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_);

Saat EIS dinonaktifkan, koordinat 3D output setara dengan koordinat 2D, dengan nilai z disetel agar tidak menghasilkan perubahan.

Mengubah shader

Koordinat 3D yang dihitung harus diteruskan ke shader rendering latar belakang. Buffer vertex kini 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 mengetahui detail selengkapnya.