„Rohtiefe“ in Ihrer Android-App verwenden

Die Raw Depth API bietet Tiefendaten für ein Kamerabild, die eine höhere Genauigkeit als volle Tiefen API-Daten aufweisen, aber nicht immer alle Pixel abdecken. Raw-Tiefenbilder mit den zugehörigen Konfidenzbildern können auch weiter verarbeitet werden, sodass Apps nur die Tiefendaten verwenden können, die für den jeweiligen Anwendungsfall eine ausreichende Genauigkeit haben.

Eingeschränkte Gerätekompatibilität

Die Rohtiefe ist auf allen Geräten verfügbar, die die Depth API unterstützen. Die Raw Depth API benötigt wie die Full Depth API keinen unterstützten Hardware-Tiefensensor, z. B. einen Time-of-Flight-Sensor (ToF). Sowohl die Raw Depth API als auch die vollständige Depth API nutzen jedoch alle unterstützten Hardwaresensoren eines Geräts.

Raw Depth API und Full Depth API im Vergleich

Die Raw Depth API bietet Tiefenschätzungen mit einer höheren Genauigkeit, aber unformatierte Tiefenbilder enthalten möglicherweise keine Tiefenschätzungen für alle Pixel im Kamerabild. Im Gegensatz dazu bietet die Full Depth API die geschätzte Tiefe für jedes Pixel. Die Tiefendaten pro Pixel sind jedoch aufgrund der Glättung und Interpolation von Tiefenschätzungen möglicherweise weniger genau. Format und Größe von Bildern mit Tiefe sind in beiden APIs identisch. Nur der Inhalt unterscheidet sich.

Die folgende Tabelle veranschaulicht die Unterschiede zwischen der Raw Depth API und der vollständigen Depth API anhand eines Bilds eines Stuhls und eines Tisches in einer Küche.

API Gibt Folgendes zurück: Kamerabild Tiefenbild Bild zu Vertrauen
Raw Depth API
  • Ein unbearbeitetes Tiefenbild, das eine sehr genaue Tiefenschätzung für einige, aber nicht alle Pixel im Kamerabild enthält.
  • Ein Konfidenzbild, das den Konfidenzwert für jedes Bildpixel mit Rohtiefe angibt. Kamerapixel ohne Tiefenschätzung haben eine Konfidenz von null.
Full Depth API
  • Eine einzelne "geglättete" Tiefenbilds, das eine Tiefenschätzung für jedes Pixel enthält.
  • Mit dieser API wird kein Bild für die Zuverlässigkeit bereitgestellt.

Konfidenzbilder

In Konfidenzbildern, die von der Raw Depth API zurückgegeben werden, haben hellere Pixel höhere Konfidenzwerte, wobei weiße Pixel das vollständige Konfidenzniveau und schwarze Pixel keine Konfidenz darstellen. Im Allgemeinen weisen Bereiche im Kamerabild mit mehr Textur, wie z. B. ein Baum, eine höhere Konfidenz der Rohqualität auf als Bereiche im Kamerabild, die dies nicht tun, z. B. eine leere Wand. Oberflächen ohne Textur haben in der Regel eine Konfidenz von null.

Wenn das Zielgerät über einen unterstützten Hardware-Tiefensensor verfügt, ist die Zuverlässigkeit in Bereichen des Bildes, die nah genug an der Kamera liegen, wahrscheinlich höher, selbst auf texturlosen Oberflächen.

Compute-Kosten

Die Computing-Kosten der Raw Depth API betragen etwa die Hälfte der Computing-Kosten für die vollständige Depth API.

Anwendungsfälle

Mit der Raw Depth API können Sie Tiefenbilder abrufen, die eine detailliertere Darstellung der Geometrie der Objekte in der Szene ermöglichen. Raw-Tiefendaten können bei der Erstellung von AR-Erlebnissen nützlich sein, bei denen für Aufgaben, die Geometrie verstehen, mehr Tiefe und Detailgenauigkeit erforderlich ist. Einige Anwendungsfälle:

  • Rekonstruktion in 3D
  • Messung
  • Formerkennung

Vorbereitung

Machen Sie sich mit den grundlegenden AR-Konzepten vertraut. und Konfigurieren einer ARCore-Sitzung beschrieben, bevor du fortfährst.

Tiefe aktivieren

Prüfen Sie in einer neuen ARCore-Sitzung, ob das Gerät des Nutzers „Tiefendaten“ unterstützt. Aufgrund von Einschränkungen bei der Prozessorleistung unterstützen nicht alle ARCore-kompatiblen Geräte die Depth API. Um Ressourcen zu sparen, ist die Tiefe in ARCore standardmäßig deaktiviert. Aktivieren Sie den Tiefenmodus, damit Ihre App die Depth API verwenden kann.

Java

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

Kotlin

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

Die neuesten Bilder zu Tiefe und Konfidenz erwerben

Rufen Sie frame.acquireRawDepthImage16Bits() auf, um das neueste unbearbeitete Tiefenbild abzurufen. Nicht alle Bildpixel, die über die Raw Depth API zurückgegeben werden, enthalten Tiefendaten und nicht jeder ARCore-Frame enthält ein neues Rohtiefenbild. Um zu ermitteln, ob das unbearbeitete Tiefenbild für den aktuellen Frame neu ist, vergleichen Sie seinen Zeitstempel mit dem Zeitstempel des vorherigen Rohtiefenbilds. Wenn sich die Zeitstempel unterscheiden, basiert das Rohtiefenbild auf neuen Tiefendaten. Andernfalls ist das Tiefenbild eine Reprojektion vorheriger Tiefendaten.

Rufen Sie frame.acquireRawDepthConfidenceImage() auf, um das Konfidenzbild zu erhalten. Sie können das Konfidenzbild verwenden, um die Genauigkeit der einzelnen Rohtiefenpixel zu überprüfen. Konfidenzbilder werden im Y8-Format zurückgegeben. Jedes Pixel ist eine vorzeichenlose 8-Bit-Ganzzahl. 0 gibt die niedrigste Zuverlässigkeit an, 255 die höchste Zuverlässigkeit.

Java

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

Kotlin

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

Weiteres Vorgehen