Sử dụng Raw Depth trong ứng dụng Android

API Độ sâu thô cung cấp dữ liệu chiều sâu cho hình ảnh máy ảnh có độ chính xác cao hơn dữ liệu API Độ sâu đầy đủ nhưng không phải lúc nào cũng bao gồm mọi pixel. Hình ảnh độ sâu thô, cùng với hình ảnh phù hợp, cũng có thể được xử lý thêm, cho phép ứng dụng chỉ sử dụng dữ liệu độ sâu có đủ độ chính xác cho trường hợp sử dụng riêng lẻ.

Khả năng tương thích với thiết bị

Nghiên cứu độ sâu thô có trên tất cả các thiết bị hỗ trợ API Độ sâu. thô Độ sâu API, giống như API Độ sâu đầy đủ, không yêu cầu cảm biến độ sâu phần cứng được hỗ trợ, chẳng hạn như cảm biến thời gian bay (ToF). Tuy nhiên, cả Raw Elevation API và API độ sâu đầy đủ đều sử dụng mọi cảm biến phần cứng được hỗ trợ mà thiết bị có thể có.

API Độ sâu thô so với API Độ sâu đầy đủ

thô độ sâu API cung cấp ước tính độ sâu với độ chính xác cao hơn, nhưng hình ảnh có chiều sâu thô có thể không bao gồm ước tính độ sâu cho tất cả các pixel trong hình ảnh máy ảnh. Ngược lại, API độ sâu đầy đủ cung cấp độ sâu ước tính cho mỗi pixel nhưng dữ liệu độ sâu trên mỗi pixel có thể kém chính xác hơn do làm mượt và nội suy ước tính độ sâu. Định dạng và kích thước của hình ảnh chiều sâu giống nhau trên cả hai API. Chỉ có phần nội dung khác biệt.

Bảng sau đây minh hoạ sự khác biệt giữa Raw Depth API và full tích API bằng cách sử dụng hình ảnh một chiếc ghế và một chiếc bàn trong nhà bếp.

API Trả bóng Hình ảnh camera Hình ảnh chi tiết Hình ảnh độ tin cậy
API Độ sâu thô
  • Hình ảnh có chiều sâu thô chứa ước tính chiều sâu rất chính xác cho một số, chứ không phải tất cả, pixel trong hình ảnh máy ảnh.
  • Hình ảnh độ tin cậy mang lại sự tin cậy cho từng pixel hình ảnh có độ sâu thô. Các pixel hình ảnh máy ảnh không có ước tính về chiều sâu có độ tin cậy bằng 0.
API Độ sâu đầy đủ
  • Một hình ảnh có chiều sâu "làm mượt" chứa ước tính độ sâu cho mỗi pixel.
  • Không có hình ảnh nào đáng tin cậy được cung cấp thông qua API này.
Không áp dụng

Hình ảnh về độ tin cậy

Trong hình ảnh độ tin cậy do Raw Depth API trả về, pixel sáng hơn có giá trị tin cậy cao hơn, trong đó pixel trắng thể hiện độ tin cậy hoàn toàn và pixel đen biểu thị không tin cậy. Nói chung, các khu vực trong hình ảnh máy ảnh có nhiều hoạ tiết hơn, chẳng hạn như cây, sẽ có độ tin cậy về độ sâu thô cao hơn so với các khu vực không có nhiều hoạ tiết, chẳng hạn như một bức tường trống. Các bề mặt không có hoạ tiết thường có độ tin cậy bằng 0.

Nếu thiết bị mục tiêu có cảm biến độ sâu phần cứng được hỗ trợ, thì độ tin cậy ở các khu vực hình ảnh đủ gần máy ảnh sẽ có thể cao hơn, ngay cả trên các bề mặt không có hoạ tiết.

Tính toán chi phí

Chi phí tính toán của Raw Depth API bằng khoảng một nửa chi phí điện toán cho toàn bộ tích API.

Trường hợp sử dụng

Thông qua API Độ sâu thô, bạn có thể thu được hình ảnh có chiều sâu mô tả chi tiết hơn về hình dạng của các đối tượng trong cảnh. Dữ liệu độ sâu thô có thể hữu ích khi tạo trải nghiệm thực tế tăng cường cần tăng độ chính xác và độ chi tiết về độ sâu để làm các nhiệm vụ tìm hiểu hình học. Một số trường hợp sử dụng bao gồm:

  • Tái tạo 3D
  • Đo lường
  • Phát hiện hình dạng

Điều kiện tiên quyết

Hãy đảm bảo bạn hiểu rõ các khái niệm cơ bản về AR và cách định cấu hình một phiên ARCore trước khi tiếp tục.

Bật độ sâu

Trong một phiên ARCore mới, hãy kiểm tra xem thiết bị của người dùng có hỗ trợ Chiều sâu hay không. Không phải thiết bị nào tương thích với ARCore đều hỗ trợ Depth API do các hạn chế về nguồn điện khi xử lý. Để tiết kiệm tài nguyên, theo mặc định, độ sâu sẽ bị tắt trên ARCore. Bật chế độ độ sâu để ứng dụng của bạn sử dụng API Độ sâu.

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

Nhận được hình ảnh có chiều sâu và độ tin cậy mới nhất

Hãy gọi frame.acquireRawDepthImage16Bits() để lấy hình ảnh chiều sâu thô mới nhất. Không phải tất cả pixel hình ảnh được trả về qua Raw Depth API (API Độ sâu thô) đều chứa dữ liệu độ sâu và không phải mọi khung ARCore đều chứa hình ảnh có độ sâu thô mới. Để xác định xem hình ảnh chiều sâu thô cho khung hiện tại có phải là hình ảnh mới hay không, hãy so sánh dấu thời gian của hình ảnh đó với dấu thời gian của hình ảnh chiều sâu thô trước đó. Nếu các dấu thời gian khác nhau, hình ảnh độ sâu thô sẽ dựa trên dữ liệu độ sâu mới. Nếu không, hình ảnh độ sâu là phép chiếu lại của dữ liệu độ sâu trước đó.

Gọi frame.acquireRawDepthConfidenceImage() để có được hình ảnh đáng tin cậy. Bạn có thể sử dụng hình ảnh độ tin cậy để kiểm tra độ chính xác của từng pixel độ sâu thô. Hình ảnh đáng tin cậy sẽ được trả về ở định dạng Y8. Mỗi pixel là một số nguyên 8 bit chưa ký. 0 cho biết mức độ tin cậy thấp nhất, trong khi 255 là mức độ tin cậy cao nhất.

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

Bước tiếp theo