แก้ภาพสั่นไหวในภาพจากกล้อง 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 เป็นเอาต์พุตเพื่อรับพิกัดอุปกรณ์ 3 มิติ และใช้ AR_COORDINATES_3D_EIS_TEXTURE_NORMALIZED เป็นเอาต์พุตเพื่อรับพิกัดพื้นผิว 3 มิติ ในขณะนี้ ประเภทพิกัดอินพุตเดียวที่สนับสนุนสำหรับ 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 ปิดอยู่ พิกัด 3 มิติเอาต์พุตจะเทียบเท่ากับพิกัด 2 มิติของค่า z โดยตั้งค่า z ไม่ให้มีการเปลี่ยนแปลง

แก้ไขตัวให้เฉดสี

พิกัด 3 มิติที่คำนวณได้ควรส่งผ่านไปยังตัวปรับแสงเงาพื้นหลัง ขณะนี้บัฟเฟอร์ Vertex เป็น 3 มิติด้วย 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 สำหรับรายละเอียดเพิ่มเติม