از ARCore به عنوان ورودی برای مدل‌های یادگیری ماشین استفاده کنید

می‌توانید از فید دوربینی که ARCore در خط لوله یادگیری ماشین ضبط می‌کند برای ایجاد یک تجربه واقعیت افزوده هوشمند استفاده کنید. نمونه ARCore ML Kit نحوه استفاده از ML Kit و Google Cloud Vision API را برای شناسایی اشیاء دنیای واقعی نشان می دهد. نمونه از یک مدل یادگیری ماشینی برای طبقه بندی اشیاء در دید دوربین استفاده می کند و یک برچسب به شی در صحنه مجازی می چسباند.

نمونه کیت ARCore ML به زبان Kotlin نوشته شده است. همچنین به عنوان برنامه نمونه ml_kotlin در مخزن ARCore SDK GitHub موجود است.

از تصویر CPU ARCore استفاده کنید

ARCore حداقل دو مجموعه از جریان های تصویر را به طور پیش فرض می گیرد:

  • یک جریان تصویر CPU که برای تشخیص ویژگی و پردازش تصویر استفاده می شود. به طور پیش فرض، تصویر CPU دارای وضوح VGA (640x480) است. ARCore را می توان برای استفاده از جریان تصویر با وضوح بالاتر در صورت لزوم پیکربندی کرد.
  • یک جریان بافت GPU ، که شامل یک بافت با وضوح بالا، معمولا با وضوح 1080p است. این معمولاً به عنوان پیش نمایش دوربین رو به روی کاربر استفاده می شود. این در بافت OpenGL که توسط Session.setCameraTextureName() مشخص شده است ذخیره می شود.
  • هر جریان اضافی مشخص شده توسط SharedCamera.setAppSurfaces() .

ملاحظات اندازه تصویر CPU

در صورت استفاده از جریان پیش‌فرض CPU با اندازه VGA، هزینه اضافی متحمل نمی‌شود زیرا ARCore از این جریان برای درک جهان استفاده می‌کند. درخواست یک جریان با وضوح متفاوت ممکن است گران باشد، زیرا یک جریان اضافی باید ضبط شود. به خاطر داشته باشید که رزولوشن بالاتر ممکن است به سرعت برای مدل شما گران شود: دوبرابر کردن عرض و ارتفاع تصویر، تعداد پیکسل های تصویر را چهار برابر می کند.

اگر مدل شما هنوز هم می‌تواند روی یک تصویر با وضوح پایین‌تر عملکرد خوبی داشته باشد، کاهش مقیاس تصویر ممکن است سودمند باشد.

یک جریان تصویر CPU با وضوح بالا اضافی را پیکربندی کنید

عملکرد مدل ML شما ممکن است به وضوح تصویر مورد استفاده به عنوان ورودی بستگی داشته باشد. وضوح این جریان ها را می توان با تغییر CameraConfig فعلی با استفاده از Session.setCameraConfig() تنظیم کرد و یک پیکربندی معتبر را از Session.getSupportedCameraConfigs() انتخاب کرد.

جاوا

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);

کاتلین

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() بازیابی کنید. این تصاویر باید به محض اینکه دیگر مورد نیاز نیستند دور ریخته شوند.

جاوا

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();
  }
}

کاتلین

// 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، می توان از کتابخانه های مختلف یادگیری ماشین استفاده کرد.

نتایج را در صحنه AR خود نمایش دهید

مدل های تشخیص تصویر اغلب اشیاء شناسایی شده را با نشان دادن یک نقطه مرکزی یا یک چندضلعی مرزی که نشان دهنده شی شناسایی شده است، خروجی می دهند.

با استفاده از نقطه مرکزی یا مرکز جعبه مرزی که از مدل خروجی می شود، می توان یک لنگر را به شی شناسایی شده متصل کرد. از Frame.hitTest() برای تخمین وضعیت یک شی در صحنه مجازی استفاده کنید.

تبدیل مختصات IMAGE_PIXELS به مختصات VIEW :

جاوا

// 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.

کاتلین

// 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 برای انجام تست ضربه و ایجاد یک لنگر از نتیجه استفاده کنید:

جاوا

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.
}

کاتلین

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.
}

ملاحظات عملکرد

برای صرفه جویی در قدرت پردازش و مصرف انرژی کمتر، توصیه های زیر را دنبال کنید:

  • مدل ML خود را روی هر فریم ورودی اجرا نکنید. به جای آن، تشخیص شی را با نرخ فریم پایین اجرا کنید.
  • برای کاهش پیچیدگی محاسباتی، یک مدل استنتاج ML آنلاین را در نظر بگیرید.

مراحل بعدی

،

می‌توانید از فید دوربینی که ARCore در خط لوله یادگیری ماشین ضبط می‌کند برای ایجاد یک تجربه واقعیت افزوده هوشمند استفاده کنید. نمونه ARCore ML Kit نحوه استفاده از ML Kit و Google Cloud Vision API را برای شناسایی اشیاء دنیای واقعی نشان می دهد. نمونه از یک مدل یادگیری ماشینی برای طبقه بندی اشیاء در دید دوربین استفاده می کند و یک برچسب به شی در صحنه مجازی می چسباند.

نمونه کیت ARCore ML به زبان Kotlin نوشته شده است. همچنین به عنوان برنامه نمونه ml_kotlin در مخزن ARCore SDK GitHub موجود است.

از تصویر CPU ARCore استفاده کنید

ARCore حداقل دو مجموعه از جریان های تصویر را به طور پیش فرض می گیرد:

  • یک جریان تصویر CPU که برای تشخیص ویژگی و پردازش تصویر استفاده می شود. به طور پیش فرض، تصویر CPU دارای وضوح VGA (640x480) است. ARCore را می توان برای استفاده از جریان تصویر با وضوح بالاتر در صورت لزوم پیکربندی کرد.
  • یک جریان بافت GPU ، که شامل یک بافت با وضوح بالا، معمولا با وضوح 1080p است. این معمولاً به عنوان پیش نمایش دوربین رو به روی کاربر استفاده می شود. این در بافت OpenGL که توسط Session.setCameraTextureName() مشخص شده است ذخیره می شود.
  • هر جریان اضافی مشخص شده توسط SharedCamera.setAppSurfaces() .

ملاحظات اندازه تصویر CPU

در صورت استفاده از جریان پیش‌فرض CPU با اندازه VGA، هزینه اضافی متحمل نمی‌شود زیرا ARCore از این جریان برای درک جهان استفاده می‌کند. درخواست یک جریان با وضوح متفاوت ممکن است گران باشد، زیرا یک جریان اضافی باید ضبط شود. به خاطر داشته باشید که رزولوشن بالاتر ممکن است به سرعت برای مدل شما گران شود: دوبرابر کردن عرض و ارتفاع تصویر، تعداد پیکسل های تصویر را چهار برابر می کند.

اگر مدل شما هنوز هم می‌تواند روی یک تصویر با وضوح پایین‌تر عملکرد خوبی داشته باشد، کاهش مقیاس تصویر ممکن است سودمند باشد.

یک جریان تصویر CPU با وضوح بالا اضافی را پیکربندی کنید

عملکرد مدل ML شما ممکن است به وضوح تصویر مورد استفاده به عنوان ورودی بستگی داشته باشد. وضوح این جریان ها را می توان با تغییر CameraConfig فعلی با استفاده از Session.setCameraConfig() تنظیم کرد و یک پیکربندی معتبر را از Session.getSupportedCameraConfigs() انتخاب کرد.

جاوا

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);

کاتلین

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() بازیابی کنید. این تصاویر باید به محض اینکه دیگر مورد نیاز نیستند دور ریخته شوند.

جاوا

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();
  }
}

کاتلین

// 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، می توان از کتابخانه های مختلف یادگیری ماشین استفاده کرد.

نتایج را در صحنه AR خود نمایش دهید

مدل های تشخیص تصویر اغلب اشیاء شناسایی شده را با نشان دادن یک نقطه مرکزی یا یک چندضلعی مرزی که نشان دهنده شی شناسایی شده است، خروجی می دهند.

با استفاده از نقطه مرکزی یا مرکز جعبه مرزی که از مدل خروجی می شود، می توان یک لنگر را به شی شناسایی شده متصل کرد. از Frame.hitTest() برای تخمین وضعیت یک شی در صحنه مجازی استفاده کنید.

تبدیل مختصات IMAGE_PIXELS به مختصات VIEW :

جاوا

// 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.

کاتلین

// 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 برای انجام تست ضربه و ایجاد یک لنگر از نتیجه استفاده کنید:

جاوا

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.
}

کاتلین

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.
}

ملاحظات عملکرد

برای صرفه جویی در قدرت پردازش و مصرف انرژی کمتر، توصیه های زیر را دنبال کنید:

  • مدل ML خود را روی هر فریم ورودی اجرا نکنید. به جای آن، تشخیص شی را با نرخ فریم پایین اجرا کنید.
  • برای کاهش پیچیدگی محاسباتی، یک مدل استنتاج ML آنلاین را در نظر بگیرید.

مراحل بعدی