Android SDK (Kotlin/Java) पर कैमरा इमेज को स्थिर करें

ARCore अब इलेक्ट्रॉनिक इमेज स्टेबलाइज़ेशन (ईआईएस) के साथ काम करता है. इसकी मदद से कैमरे से, वीडियो की क्वालिटी को आसानी से देखा जा सकता है. ईआईएस, जाइरो का इस्तेमाल करके फ़ोन की हलचल को मॉनिटर करता है और कैमरे के टेक्स्चर की सीमाओं में मुआवज़ा होमोग्राफ़ी मेश लागू करके, स्टेबलाइज़ेशन हासिल करता है. यह ऐसा करने से, छोटे-छोटे झटकों का पता चलता है. ईआईएस सिर्फ़ डिवाइस के पोर्ट्रेट ओरिएंटेशन में काम करता है. सभी ओरिएंटेशन (स्क्रीन की दिशा) ARCore के 1.39.0 रिलीज़ में काम करेंगे.

ईआईएस सहायता के लिए क्वेरी करें और ईआईएस चालू करें

ईआईएस चालू करने के लिए, ImageStabilizationMode.EIS का इस्तेमाल करने के लिए अपने सेशन को कॉन्फ़िगर करें. अगर डिवाइस में EIS की सुविधा काम नहीं करती है, तो इसकी वजह से ARCore का इस्तेमाल किया जा सकता है.

Java

if (!session.isImageStabilizationModeSupported(Config.ImageStabilizationMode.EIS)) {
  return;
}
Config config = session.getConfig();
config.setImageStabilizationMode(Config.ImageStabilizationMode.EIS);
session.configure(config);

Kotlin

if (!session.isImageStabilizationModeSupported(Config.ImageStabilizationMode.EIS)) return
session.configure(
  session.config.apply { imageStabilizationMode = Config.ImageStabilizationMode.EIS }
)

निर्देशांक बदलना

ईआईएस चालू होने पर, रेंडरर को डिवाइस के बदले हुए कोऑर्डिनेट और मिलते-जुलते टेक्सचर कोऑर्डिनेट का इस्तेमाल करना होता है. साथ ही, कैमरे के बैकग्राउंड को रेंडर करते समय, ईआईएस मुआवज़ा शामिल होता है. ईआईएस के लिए पैसे कमाने वाले कोऑर्डिनेट पाने के लिए, इनपुट के तौर पर OPENGL_NORMALIZED_DEVICE_COORDINATES का और आउटपुट के तौर पर EIS_NORMALIZED_DEVICE_COORDINATES को आउटपुट के तौर पर, Frame.transformCoordinates3d() का इस्तेमाल करें और 3D टेक्सचर कोऑर्डिनेट पाने के लिए, आउटपुट के तौर पर EIS_TEXTURE_NORMALIZED का इस्तेमाल करें. फ़िलहाल, Frame.transformCoordinates3d() के लिए सिर्फ़ OPENGL_NORMALIZED_DEVICE_COORDINATES इनपुट कोऑर्डिनेट टाइप इस्तेमाल किया जा सकता है.

Java

final FloatBuffer cameraTexCoords =
    ByteBuffer.allocateDirect(COORDS_BUFFER_SIZE_3D)
        .order(ByteOrder.nativeOrder())
        .asFloatBuffer();

final FloatBuffer screenCoords =
    ByteBuffer.allocateDirect(COORDS_BUFFER_SIZE_3D)
        .order(ByteOrder.nativeOrder())
        .asFloatBuffer();

final FloatBuffer NDC_QUAD_COORDS_BUFFER =
    ByteBuffer.allocateDirect(COORDS_BUFFER_SIZE_2D)
        .order(ByteOrder.nativeOrder())
        .asFloatBuffer()
        .put(
            new float[] {
              /*0:*/ -1f, -1f, /*1:*/ +1f, -1f, /*2:*/ -1f, +1f, /*3:*/ +1f, +1f,
            });

final VertexBuffer screenCoordsVertexBuffer =
    new VertexBuffer(render, /* numberOfEntriesPerVertex= */ 3, null);
final VertexBuffer cameraTexCoordsVertexBuffer =
    new VertexBuffer(render, /* numberOfEntriesPerVertex= */ 3, null);

NDC_QUAD_COORDS_BUFFER.rewind();
frame.transformCoordinates3d(
    Coordinates2d.OPENGL_NORMALIZED_DEVICE_COORDINATES,
    NDC_QUAD_COORDS_BUFFER,
    Coordinates3d.EIS_NORMALIZED_DEVICE_COORDINATES,
    screenCoords);
screenCoordsVertexBuffer.set(screenCoords);

NDC_QUAD_COORDS_BUFFER.rewind();
frame.transformCoordinates3d(
    Coordinates2d.OPENGL_NORMALIZED_DEVICE_COORDINATES,
    NDC_QUAD_COORDS_BUFFER,
    Coordinates3d.EIS_TEXTURE_NORMALIZED,
    cameraTexCoords);
cameraTexCoordsVertexBuffer.set(cameraTexCoords);

Kotlin

val COORDS_BUFFER_SIZE_2D = 2 * 4 * Float.SIZE_BYTES
val COORDS_BUFFER_SIZE_3D = 3 * 4 * Float.SIZE_BYTES
val cameraTexCoords =
  ByteBuffer.allocateDirect(COORDS_BUFFER_SIZE_3D)
    .order(ByteOrder.nativeOrder())
    .asFloatBuffer()
val screenCoords =
  ByteBuffer.allocateDirect(COORDS_BUFFER_SIZE_3D)
    .order(ByteOrder.nativeOrder())
    .asFloatBuffer()
val cameraTexCoordsVertexBuffer = VertexBuffer(render, /* numberOfEntriesPerVertex= */ 3, null)
val screenCoordsVertexBuffer = VertexBuffer(render, /* numberOfEntriesPerVertex= */ 3, null)
val NDC_QUAD_COORDS_BUFFER =
  ByteBuffer.allocateDirect(COORDS_BUFFER_SIZE_2D)
    .order(ByteOrder.nativeOrder())
    .asFloatBuffer()
    .apply {
      put(
        floatArrayOf(
          /* 0: */
          -1f,
          -1f,
          /* 1: */
          +1f,
          -1f,
          /* 2: */
          -1f,
          +1f,
          /* 3: */
          +1f,
          +1f
        )
      )
    }
NDC_QUAD_COORDS_BUFFER.rewind()
frame.transformCoordinates3d(
  Coordinates2d.OPENGL_NORMALIZED_DEVICE_COORDINATES,
  NDC_QUAD_COORDS_BUFFER,
  Coordinates3d.EIS_NORMALIZED_DEVICE_COORDINATES,
  screenCoords
)
screenCoordsVertexBuffer.set(screenCoords)

NDC_QUAD_COORDS_BUFFER.rewind()
frame.transformCoordinates3d(
  Coordinates2d.OPENGL_NORMALIZED_DEVICE_COORDINATES,
  NDC_QUAD_COORDS_BUFFER,
  Coordinates3d.EIS_TEXTURE_NORMALIZED,
  cameraTexCoords
)
cameraTexCoordsVertexBuffer.set(cameraTexCoords)

ईआईएस के बंद होने पर, आउटपुट 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 सैंपल ऐप्लिकेशन देखें.