استخدام ARCore كإدخال لنماذج تعلُّم الآلة

يمكنك استخدام خلاصة الكاميرا التي يلتقطها ARCore في مسار تعلُّم الآلة لإنشاء تجربة ذكية بتقنية الواقع المعزّز. يوضّح نموذج ARCore ML Kit كيفية استخدام ML Kit وGoogle Cloud Vision API لتحديد العناصر في الواقع. يستخدم النموذج نموذج تعلُّم الآلة لتصنيف العناصر في عرض الكاميرا وإرفاق تصنيف بالكائن في المشهد الافتراضي.

تمت كتابة نموذج ARCore ML Kit باستخدام لغة Kotlin. وهو متاح أيضًا على أنه نموذج ml_kotlin في مستودع GitHub ARCore SDK.

استخدام صورة وحدة المعالجة المركزية (CPU) من ARCore

يلتقط ARCore مجموعتين على الأقل من مجموعات بث الصور تلقائيًا:

  • مصدر بيانات صورة وحدة المعالجة المركزية (CPU) يُستخدم للتعرّف على الميزات ومعالجة الصور. بشكل افتراضي، تبلغ دقة صورة وحدة المعالجة المركزية VGA (640×480). يمكن ضبط ARCore لاستخدام مجموعة بث إضافية للصور بدرجة دقة أعلى، إذا لزم الأمر.
  • تدفق زخرفة وحدة معالجة الرسومات الذي يحتوي على زخرفة عالية الدقة، عادة بدرجة دقة 1080p. تُستخدَم هذه الصورة عادةً كمعاينة للكاميرا موجّهة للمستخدم. يتم تخزين هذا الرقم في زخرفة OpenGL التي يتم تحديدها من خلال Session.setCameraTextureName().
  • أي أحداث بث إضافية تحدّدها SharedCamera.setAppSurfaces().

اعتبارات حجم صورة وحدة المعالجة المركزية (CPU)

لن يتم تحصيل أي تكلفة إضافية في حال استخدام بث وحدة المعالجة المركزية (CPU) التلقائي بحجم VGA لأن ARCore يستخدم هذا البث ليفهمه للجميع. قد يكون طلب بث بدقة مختلفة أمرًا مكلفًا، لأنّه يجب تسجيل بث إضافي. ضع في اعتبارك أن الدقة الأعلى قد تصبح مكلفة بسرعة بالنسبة لنموذجك: مضاعفة عرض الصورة وارتفاعها يساوي أربعة أضعاف مقدار البكسل في الصورة.

قد يكون من المفيد تخفيض حجم الصورة إذا كان نموذجك لا يزال يحقق أداءً جيدًا مع صورة ذات دقة أقل.

إعداد بث إضافي لصور وحدة المعالجة المركزية (CPU) بدقة عالية

قد يعتمد أداء نموذج تعلُّم الآلة على درجة دقة الصورة المستخدَمة كإدخال. يمكن تعديل درجة دقة ساحات المشاركات هذه من خلال تغيير CameraConfig الحالي باستخدام Session.setCameraConfig()، واختيار إعداد صالح من 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)

استرداد صورة وحدة المعالجة المركزية (CPU)

يمكنك استرداد صورة وحدة المعالجة المركزية (CPU) باستخدام 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.
}

معالجة صورة وحدة المعالجة المركزية (CPU)

لمعالجة صورة وحدة المعالجة المركزية (CPU)، يمكن استخدام مكتبات مختلفة لتعلُّم الآلة.

عرض النتائج في مشهد الواقع المعزّز

غالبًا ما تُخرج نماذج التعرّف على الصور العناصر المكتشفة من خلال الإشارة إلى نقطة مركزية أو مضلّع محيط يمثّل الكائن الذي تم اكتشافه.

باستخدام النقطة المركزية أو مركز مربع الإحاطة الذي يتم إخراجه من النموذج، يمكن تثبيت علامة ارتساء بالكائن المكتشف. استخدِم 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.
}

اعتبارات الأداء

يمكنك اتّباع النصائح التالية لتوفير طاقة المعالجة واستهلاك طاقة أقل:

  • ولا تستخدِم نموذج تعلُّم الآلة على كل إطار وارد. ننصحك بتفعيل ميزة رصد الأجسام بعدد لقطات منخفض في الثانية بدلاً من ذلك.
  • يمكنك الاستعانة بنموذج استنتاج تعلُّم الآلة على الإنترنت لتقليل التعقيد الحاسوبي.

الخطوات التالية