मशीन लर्निंग मॉडल में इनपुट के तौर पर ARCore का इस्तेमाल करना

आप बेहतर ऑगमेंटेड रिएलिटी (एआर) का अनुभव देने के लिए, उस कैमरा फ़ीड का इस्तेमाल कर सकते हैं जिसे ARCore ने मशीन लर्निंग पाइपलाइन में कैप्चर किया है. ARCore ML Kit सैंपल से, असल दुनिया के ऑब्जेक्ट की पहचान करने के लिए, ML Kit और Google Cloud Vision API को इस्तेमाल करने का तरीका पता चलता है. यह नमूना, कैमरे के व्यू में मौजूद ऑब्जेक्ट की कैटगरी तय करने के लिए मशीन लर्निंग मॉडल का इस्तेमाल करता है. साथ ही, वर्चुअल सीन में मौजूद ऑब्जेक्ट पर एक लेबल जोड़ता है.

ARCore ML Kit सैंपल को Kotlin में लिखा जाता है. यह ARCore SDK GitHub रिपॉज़िटरी में, ml_kotlin सैंपल ऐप्लिकेशन के तौर पर भी उपलब्ध है.

ARCore के सीपीयू इमेज का इस्तेमाल करें

ARCore डिफ़ॉल्ट रूप से, इमेज स्ट्रीम के कम से कम दो सेट कैप्चर करता है:

  • सीपीयू इमेज स्ट्रीम का इस्तेमाल, सुविधा की पहचान करने और इमेज प्रोसेसिंग के लिए किया जाता है. डिफ़ॉल्ट रूप से, सीपीयू इमेज का रिज़ॉल्यूशन वीजीए (640x480) होता है. ज़रूरत पड़ने पर, ज़्यादा रिज़ॉल्यूशन वाली इमेज स्ट्रीम का इस्तेमाल करने के लिए, ARCore को कॉन्फ़िगर किया जा सकता है.
  • GPU टेक्सचर स्ट्रीम, जिसमें हाई रिज़ॉल्यूशन वाला टेक्सचर होता है. आम तौर पर, इसका रिज़ॉल्यूशन 1080 पिक्सल होता है. आम तौर पर, इसका इस्तेमाल कैमरे की झलक के तौर पर किया जाता है. यह Session.setCameraTextureName() के बताए गए OpenGL टेक्सचर में स्टोर किया जाता है.
  • SharedCamera.setAppSurfaces() से तय की गई कोई भी अतिरिक्त स्ट्रीम.

सीपीयू की इमेज के साइज़ से जुड़ी खास बातें

अगर डिफ़ॉल्ट वीजीए के आकार की सीपीयू स्ट्रीम का इस्तेमाल किया जाता है, तो अलग से कोई शुल्क नहीं लिया जाता है, क्योंकि ARCore दुनिया को समझने के लिए इस स्ट्रीम का इस्तेमाल करता है. किसी दूसरे रिज़ॉल्यूशन वाली स्ट्रीम के लिए अनुरोध करना महंगा हो सकता है, क्योंकि एक और स्ट्रीम को कैप्चर करने की ज़रूरत होती है. ध्यान रखें कि ज़्यादा रिज़ॉल्यूशन वाला आपके मॉडल के लिए जल्द महंगा हो सकता है: इमेज की चौड़ाई और ऊंचाई को दोगुना करने पर, इमेज में मौजूद पिक्सल की संख्या दोगुनी हो जाएगी.

अगर आपका मॉडल अब भी कम रिज़ॉल्यूशन वाली इमेज पर अच्छा परफ़ॉर्म कर सकता है, तो इमेज का साइज़ कम करने से फ़ायदा हो सकता है.

अतिरिक्त हाई रिज़ॉल्यूशन सीपीयू इमेज स्ट्रीम कॉन्फ़िगर करें

आपके एमएल मॉडल की परफ़ॉर्मेंस, इनपुट के तौर पर इस्तेमाल की गई इमेज के रिज़ॉल्यूशन पर निर्भर कर सकती है. इन स्ट्रीम के रिज़ॉल्यूशन में बदलाव करने के लिए, Session.setCameraConfig() का इस्तेमाल करके मौजूदा CameraConfig को बदला जा सकता है. इसके लिए, Session.getSupportedCameraConfigs() से कोई मान्य कॉन्फ़िगरेशन चुनें.

Java

CameraConfigFilter cameraConfigFilter =
    new CameraConfigFilter(session)
        // World-facing cameras only.
        .setFacingDirection(CameraConfig.FacingDirection.BACK);
List<CameraConfig> supportedCameraConfigs =
    session.getSupportedCameraConfigs(cameraConfigFilter);

// Select an acceptable configuration from supportedCameraConfigs.
CameraConfig cameraConfig = selectCameraConfig(supportedCameraConfigs);
session.setCameraConfig(cameraConfig);

Kotlin

val cameraConfigFilter =
  CameraConfigFilter(session)
    // World-facing cameras only.
    .setFacingDirection(CameraConfig.FacingDirection.BACK)
val supportedCameraConfigs = session.getSupportedCameraConfigs(cameraConfigFilter)

// Select an acceptable configuration from supportedCameraConfigs.
val cameraConfig = selectCameraConfig(supportedCameraConfigs)
session.setCameraConfig(cameraConfig)

सीपीयू की इमेज वापस पाएं

Frame.acquireCameraImage() का इस्तेमाल करके सीपीयू इमेज वापस पाएं. ज़रूरत न होने पर, इन इमेज को जल्द से जल्द मिटा दिया जाना चाहिए.

Java

Image cameraImage = null;
try {
  cameraImage = frame.acquireCameraImage();
  // Process `cameraImage` using your ML inference model.
} catch (NotYetAvailableException e) {
  // NotYetAvailableException is an exception that can be expected when the camera is not ready
  // yet. The image may become available on a next frame.
} catch (RuntimeException e) {
  // A different exception occurred, e.g. DeadlineExceededException, ResourceExhaustedException.
  // Handle this error appropriately.
  handleAcquireCameraImageFailure(e);
} finally {
  if (cameraImage != null) {
    cameraImage.close();
  }
}

Kotlin

// NotYetAvailableException is an exception that can be expected when the camera is not ready yet.
// Map it to `null` instead, but continue to propagate other errors.
fun Frame.tryAcquireCameraImage() =
  try {
    acquireCameraImage()
  } catch (e: NotYetAvailableException) {
    null
  } catch (e: RuntimeException) {
    // A different exception occurred, e.g. DeadlineExceededException, ResourceExhaustedException.
    // Handle this error appropriately.
    handleAcquireCameraImageFailure(e)
  }

// The `use` block ensures the camera image is disposed of after use.
frame.tryAcquireCameraImage()?.use { image ->
  // Process `image` using your ML inference model.
}

सीपीयू इमेज प्रोसेस करें

सीपीयू इमेज को प्रोसेस करने के लिए, अलग-अलग मशीन लर्निंग लाइब्रेरी का इस्तेमाल किया जा सकता है.

नतीजे अपने एआर सीन में दिखाएं

इमेज की पहचान करने वाले मॉडल, अक्सर पता लगाए गए ऑब्जेक्ट को सेंटर पॉइंट या बाउंडिंग पॉलीगॉन की मदद से दिखाते हैं.

मॉडल से आउटपुट होने वाले बाउंडिंग बॉक्स के केंद्र बिंदु या केंद्र का इस्तेमाल करके, पता लगाए गए ऑब्जेक्ट में ऐंकर जोड़ा जा सकता है. वर्चुअल सीन में किसी चीज़ के पोज़ का अनुमान लगाने के लिए, Frame.hitTest() का इस्तेमाल करें.

IMAGE_PIXELS निर्देशांक को VIEW निर्देशांक में बदलें:

Java

// Suppose `mlResult` contains an (x, y) of a given point on the CPU image.
float[] cpuCoordinates = new float[] {mlResult.getX(), mlResult.getY()};
float[] viewCoordinates = new float[2];
frame.transformCoordinates2d(
    Coordinates2d.IMAGE_PIXELS, cpuCoordinates, Coordinates2d.VIEW, viewCoordinates);
// `viewCoordinates` now contains coordinates suitable for hit testing.

Kotlin

// Suppose `mlResult` contains an (x, y) of a given point on the CPU image.
val cpuCoordinates = floatArrayOf(mlResult.x, mlResult.y)
val viewCoordinates = FloatArray(2)
frame.transformCoordinates2d(
  Coordinates2d.IMAGE_PIXELS,
  cpuCoordinates,
  Coordinates2d.VIEW,
  viewCoordinates
)
// `viewCoordinates` now contains coordinates suitable for hit testing.

हिट की जांच करने और नतीजे से ऐंकर बनाने के लिए, इन VIEW कोऑर्डिनेट का इस्तेमाल करें:

Java

List<HitResult> hits = frame.hitTest(viewCoordinates[0], viewCoordinates[1]);
HitResult depthPointResult = null;
for (HitResult hit : hits) {
  if (hit.getTrackable() instanceof DepthPoint) {
    depthPointResult = hit;
    break;
  }
}
if (depthPointResult != null) {
  Anchor anchor = depthPointResult.getTrackable().createAnchor(depthPointResult.getHitPose());
  // This anchor will be attached to the scene with stable tracking.
  // It can be used as a position for a virtual object, with a rotation prependicular to the
  // estimated surface normal.
}

Kotlin

val hits = frame.hitTest(viewCoordinates[0], viewCoordinates[1])
val depthPointResult = hits.filter { it.trackable is DepthPoint }.firstOrNull()
if (depthPointResult != null) {
  val anchor = depthPointResult.trackable.createAnchor(depthPointResult.hitPose)
  // This anchor will be attached to the scene with stable tracking.
  // It can be used as a position for a virtual object, with a rotation prependicular to the
  // estimated surface normal.
}

प्रदर्शन संबंधी विचार

प्रोसेसिंग पावर बचाने और ऊर्जा की कम खपत करने के लिए, इन सुझावों को अपनाएं:

  • आने वाले हर फ़्रेम पर एमएल मॉडल न चलाएं. इसके बजाय, कम फ़्रेमरेट पर ऑब्जेक्ट की पहचान करने की सुविधा का इस्तेमाल करें.
  • कंप्यूटेशनल जटिलता को कम करने के लिए, ऑनलाइन एमएल अनुमान के मॉडल का इस्तेमाल करें.

अगले चरण