Вы можете использовать изображение с камеры, которое ARCore захватывает в конвейере машинного обучения, для создания интеллектуального опыта дополненной реальности. Образец набора ARCore ML демонстрирует, как использовать ML Kit и API Google Cloud Vision для идентификации объектов реального мира. В образце используется модель машинного обучения для классификации объектов в поле зрения камеры и прикрепления метки к объекту в виртуальной сцене.
Образец набора ARCore ML написан на Kotlin. Он также доступен в виде примера приложения ml_kotlin в репозитории ARCore SDK GitHub.
Используйте образ процессора ARCore
По умолчанию ARCore захватывает как минимум два набора потоков изображений:
- Поток изображений ЦП, используемый для распознавания функций и обработки изображений. По умолчанию изображение ЦП имеет разрешение VGA (640x480). При необходимости ARCore можно настроить на использование дополнительного потока изображений с более высоким разрешением.
- Поток текстур графического процессора , который содержит текстуру высокого разрешения, обычно 1080p. Обычно это используется в качестве предварительного просмотра камеры, обращенной к пользователю. Это хранится в текстуре OpenGL, указанной
Session.setCameraTextureName()
. - Любые дополнительные потоки, указанные
SharedCamera.setAppSurfaces()
.
Рекомендации по размеру образа ЦП
Никаких дополнительных затрат не возникает, если используется поток ЦП по умолчанию размером VGA, поскольку ARCore использует этот поток для понимания мира. Запрос потока с другим разрешением может оказаться дорогостоящим, поскольку потребуется захватить дополнительный поток. Имейте в виду, что более высокое разрешение может быстро стать дорогостоящим для вашей модели: удвоение ширины и высоты изображения увеличивает количество пикселей в изображении в четыре раза.
Возможно, будет полезно уменьшить масштаб изображения, если ваша модель по-прежнему может хорошо работать с изображением с более низким разрешением.
Настройте дополнительный поток изображений ЦП высокого разрешения.
Производительность вашей модели машинного обучения может зависеть от разрешения изображения, используемого в качестве входных данных. Разрешение этих потоков можно настроить, изменив текущую 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)
Получить образ процессора
Получите изображение процессора с помощью 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. }
Обработка образа процессора
Для обработки образа ЦП можно использовать различные библиотеки машинного обучения.
- ML Kit : ML Kit предоставляет API обнаружения и отслеживания объектов на устройстве. Он поставляется со встроенным в API грубым классификатором, а также может использовать пользовательские модели классификации для охвата более узкой области объектов. Используйте
InputImage.fromMediaImage
, чтобы преобразовать образ вашего процессора вInputImage
. - Машинное обучение Firebase : Firebase предоставляет API-интерфейсы машинного обучения , которые работают либо в облаке, либо на устройстве. См. документацию Firebase по безопасной маркировке изображений с помощью Cloud Vision с использованием Firebase Auth и функций на Android .
Отображение результатов в вашей 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, чтобы уменьшить сложность вычислений.
Следующие шаги
- Узнайте о лучших практиках разработки машинного обучения .
- Узнайте о практиках ответственного ИИ .
- Изучите основы машинного обучения с курсом TensorFlow .
Вы можете использовать изображение с камеры, которое ARCore захватывает в конвейере машинного обучения, для создания интеллектуального опыта дополненной реальности. Образец ARCore ML Kit демонстрирует, как использовать ML Kit и API Google Cloud Vision для идентификации реальных объектов. В образце используется модель машинного обучения для классификации объектов в поле зрения камеры и прикрепления метки к объекту в виртуальной сцене.
Образец набора ARCore ML написан на Kotlin. Он также доступен в виде примера приложения ml_kotlin в репозитории ARCore SDK GitHub.
Используйте образ процессора ARCore
По умолчанию ARCore захватывает как минимум два набора потоков изображений:
- Поток изображений ЦП, используемый для распознавания функций и обработки изображений. По умолчанию изображение ЦП имеет разрешение VGA (640x480). При необходимости ARCore можно настроить на использование дополнительного потока изображений с более высоким разрешением.
- Поток текстур графического процессора , который содержит текстуру высокого разрешения, обычно 1080p. Обычно это используется в качестве предварительного просмотра камеры, обращенной к пользователю. Это хранится в текстуре OpenGL, указанной
Session.setCameraTextureName()
. - Любые дополнительные потоки, указанные
SharedCamera.setAppSurfaces()
.
Рекомендации по размеру образа ЦП
Никаких дополнительных затрат не возникает, если используется поток ЦП по умолчанию размером VGA, поскольку ARCore использует этот поток для понимания мира. Запрос потока с другим разрешением может оказаться дорогостоящим, поскольку потребуется захватить дополнительный поток. Имейте в виду, что более высокое разрешение может быстро стать дорогостоящим для вашей модели: удвоение ширины и высоты изображения увеличивает количество пикселей в изображении в четыре раза.
Возможно, будет полезно уменьшить масштаб изображения, если ваша модель по-прежнему может хорошо работать с изображением с более низким разрешением.
Настройте дополнительный поток изображений ЦП высокого разрешения.
Производительность вашей модели машинного обучения может зависеть от разрешения изображения, используемого в качестве входных данных. Разрешение этих потоков можно настроить, изменив текущую 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)
Получить образ процессора
Получите изображение процессора с помощью 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. }
Обработка образа процессора
Для обработки образа ЦП можно использовать различные библиотеки машинного обучения.
- ML Kit : ML Kit предоставляет API обнаружения и отслеживания объектов на устройстве. Он поставляется со встроенным в API грубым классификатором, а также может использовать пользовательские модели классификации для охвата более узкой области объектов. Используйте
InputImage.fromMediaImage
, чтобы преобразовать образ вашего процессора вInputImage
. - Машинное обучение Firebase : Firebase предоставляет API-интерфейсы машинного обучения , которые работают либо в облаке, либо на устройстве. См. документацию Firebase по безопасной маркировке изображений с помощью Cloud Vision с использованием Firebase Auth и функций на Android .
Отображение результатов в вашей 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, чтобы уменьшить сложность вычислений.
Следующие шаги
- Узнайте о лучших практиках разработки машинного обучения .
- Узнайте о практиках ответственного ИИ .
- Изучите основы машинного обучения с курсом TensorFlow .