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

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

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

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

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

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

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

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

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

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

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