Вы можете использовать изображение с камеры, которое 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 .