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

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

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

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

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

  • सीपीयू इमेज स्ट्रीम, जिसका इस्तेमाल सुविधा की पहचान करने और इमेज प्रोसेसिंग के लिए किया जाता है. डिफ़ॉल्ट रूप से, सीपीयू इमेज का रिज़ॉल्यूशन वीजीए (640x480) होता है. ज़रूरत पड़ने पर, ARCore को ज़्यादा रिज़ॉल्यूशन वाली इमेज स्ट्रीम का इस्तेमाल करने के लिए कॉन्फ़िगर किया जा सकता है.
  • जीपीयू टेक्सचर स्ट्रीम, जिसमें हाई-रिज़ॉल्यूशन वाला टेक्सचर शामिल होता है. आम तौर पर, इसका रिज़ॉल्यूशन 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.
}

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

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

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

अगले चरण