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를 출력으로 사용하여 3D 기기 좌표를 가져오고 AR_COORDINATES_3D_EIS_TEXTURE_NORMALIZED을 출력으로 사용하여 3D 텍스처 좌표를 가져옵니다. 현재 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가 사용 중지되어 있으면 출력 3D 좌표는 2D 좌표와 동일하며, z 값이 변경되지 않도록 설정됩니다.

셰이더 수정

계산된 3D 좌표는 백그라운드 렌더링 셰이더에 전달되어야 합니다. 꼭짓점 버퍼는 이제 EIS를 사용하여 3D입니다.

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 샘플 앱을 참고하세요.