Используйте Raw Depth в своем приложении для Android

API Raw Depth предоставляет данные о глубине для изображения с камеры, которые имеют более высокую точность, чем данные API полной глубины, но не всегда охватывают каждый пиксель. Необработанные изображения глубины вместе с соответствующими им достоверными изображениями также могут быть дополнительно обработаны, что позволяет приложениям использовать только те данные о глубине, которые имеют достаточную точность для их индивидуального варианта использования.

Совместимость устройств

Raw Depth доступен на всех устройствах, поддерживающих Depth API . API Raw Depth, как и API Full Depth, не требует поддерживаемого аппаратного датчика глубины, такого как датчик времени пролета (ToF). Однако как Raw Depth API, так и Full Depth API используют любые поддерживаемые аппаратные датчики, которые могут быть на устройстве.

API необработанной глубины и API полной глубины

API Raw Depth предоставляет оценки глубины с более высокой точностью, но необработанные изображения глубины могут не включать оценки глубины для всех пикселей изображения с камеры. Напротив, API полной глубины предоставляет оценку глубины для каждого пикселя, но данные о глубине для каждого пикселя могут быть менее точными из-за сглаживания и интерполяции оценок глубины. Формат и размер изображений глубины одинаковы для обоих API. Отличается только содержание.

В следующей таблице показаны различия между API Raw Depth и API Full Depth с использованием изображения стула и стола на кухне.

API Возврат Изображение с камеры Изображение глубины Уверенный образ
API необработанной глубины
  • Необработанное изображение глубины, содержащее очень точную оценку глубины для некоторых, но не всех пикселей изображения с камеры.
  • Уверенное изображение, которое дает уверенность каждому пикселю необработанного изображения глубины. Пиксели изображения камеры, у которых нет оценки глубины, имеют нулевую достоверность.
Полная глубина API
  • Одно «сглаженное» изображение глубины, содержащее оценку глубины для каждого пикселя.
  • С помощью этого API не предоставляется достоверное изображение.
Н/Д

Изображения уверенности

В достоверных изображениях, возвращаемых API Raw Depth, более светлые пиксели имеют более высокие значения достоверности: белые пиксели представляют полную достоверность, а черные — отсутствие достоверности. В целом, области изображения с камеры, имеющие больше текстуры, например дерево, будут иметь более высокую достоверность глубины, чем области без нее, например глухая стена. Поверхности без текстуры обычно дают нулевую достоверность.

Если целевое устройство имеет поддерживаемый аппаратный датчик глубины, достоверность в областях изображения, достаточно близких к камере, вероятно, будет выше, даже на бестекстурных поверхностях.

Рассчитать стоимость

Стоимость вычислений для API Raw Depth составляет примерно половину стоимости вычислений для API полной глубины.

Случаи использования

С помощью API Raw Depth вы можете получать изображения глубины, которые обеспечивают более детальное представление геометрии объектов на сцене. Необработанные данные о глубине могут быть полезны при создании AR-приложений, где для задач понимания геометрии требуется повышенная точность и детализация глубины. Некоторые варианты использования включают в себя:

  • 3D реконструкция
  • Измерение
  • Обнаружение формы

Предварительные условия

Прежде чем продолжить, убедитесь, что вы понимаете фундаментальные концепции AR и то, как настроить сеанс ARCore .

Включить глубину

В новом сеансе ARCore проверьте, поддерживает ли устройство пользователя Depth. Не все ARCore-совместимые устройства поддерживают Depth API из-за ограничений вычислительной мощности. Для экономии ресурсов глубина в ARCore по умолчанию отключена. Включите режим глубины, чтобы ваше приложение использовало Depth API.

Джава

Config config = session.getConfig();

// Check whether the user's device supports Depth.
if (session.isDepthModeSupported(Config.DepthMode.AUTOMATIC)) {
  // Enable depth mode.
  config.setDepthMode(Config.DepthMode.AUTOMATIC);
}
session.configure(config);

Котлин

if (session.isDepthModeSupported(Config.DepthMode.AUTOMATIC)) {
  session.configure(session.config.apply { depthMode = Config.DepthMode.AUTOMATIC })
}

Получайте новейшие необработанные изображения глубины и уверенности.

Вызовите frame.acquireRawDepthImage16Bits() , чтобы получить последнее необработанное изображение глубины. Не все пиксели изображения, возвращаемые через API Raw Depth, будут содержать данные глубины, и не каждый кадр ARCore будет содержать новое необработанное изображение глубины. Чтобы определить, является ли необработанное изображение глубины для текущего кадра новым, сравните его временную метку с временной меткой предыдущего необработанного изображения глубины. Если временные метки разные, необработанное изображение глубины основывается на новых данных о глубине. В противном случае изображение глубины представляет собой перепроекцию предыдущих данных глубины.

Вызовите frame.acquireRawDepthConfidenceImage() , чтобы получить достоверное изображение. Вы можете использовать доверительное изображение, чтобы проверить точность каждого необработанного пикселя глубины. Изображения уверенности возвращаются в формате Y8. Каждый пиксель представляет собой 8-битное целое число без знака. 0 означает наименьшую достоверность, а 255 — наибольшую.

Джава

// Use try-with-resources, so that images are released automatically.
try (
// Depth image is in uint16, at GPU aspect ratio, in native orientation.
Image rawDepth = frame.acquireRawDepthImage16Bits();
    // Confidence image is in uint8, matching the depth image size.
    Image rawDepthConfidence = frame.acquireRawDepthConfidenceImage(); ) {
  // Compare timestamps to determine whether depth is is based on new
  // depth data, or is a reprojection based on device movement.
  boolean thisFrameHasNewDepthData = frame.getTimestamp() == rawDepth.getTimestamp();
  if (thisFrameHasNewDepthData) {
    ByteBuffer depthData = rawDepth.getPlanes()[0].getBuffer();
    ByteBuffer confidenceData = rawDepthConfidence.getPlanes()[0].getBuffer();
    int width = rawDepth.getWidth();
    int height = rawDepth.getHeight();
    someReconstructionPipeline.integrateNewImage(depthData, confidenceData, width, height);
  }
} catch (NotYetAvailableException e) {
  // Depth image is not (yet) available.
}

Котлин

try {
  // Depth image is in uint16, at GPU aspect ratio, in native orientation.
  frame.acquireRawDepthImage16Bits().use { rawDepth ->
    // Confidence image is in uint8, matching the depth image size.
    frame.acquireRawDepthConfidenceImage().use { rawDepthConfidence ->
      // Compare timestamps to determine whether depth is is based on new
      // depth data, or is a reprojection based on device movement.
      val thisFrameHasNewDepthData = frame.timestamp == rawDepth.timestamp
      if (thisFrameHasNewDepthData) {
        val depthData = rawDepth.planes[0].buffer
        val confidenceData = rawDepthConfidence.planes[0].buffer
        val width = rawDepth.width
        val height = rawDepth.height
        someReconstructionPipeline.integrateNewImage(
          depthData,
          confidenceData,
          width = width,
          height = height
        )
      }
    }
  }
} catch (e: NotYetAvailableException) {
  // Depth image is not (yet) available.
}

Что дальше