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

API Độ sâu thô cung cấp dữ liệu về độ 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 điểm ảnh. Hình ảnh chiều sâu thô cùng với hình ảnh tin cậy phù hợp cũng có thể được xử lý thêm. Nhờ đó, các ứng dụng chỉ sử dụng dữ liệu chiề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ị

Độ sâu thô có trên tất cả thiết bị hỗ trợ depth API. Data depth API (chẳng hạn như API độ sâu đầy đủ) không yêu cầu phải có 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ả API Chiều sâu thô 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ô và API độ sâu đầy đủ

API Chiều sâu thô cung cấp số liệu ước tính về độ sâu với độ chính xác cao hơn, nhưng hình ảnh chiều sâu thô có thể không bao gồm số liệu ước tính về độ sâu cho tất cả các pixel trong hình ảnh camera. 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 về độ 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 ảnh chiều sâu giống nhau trên cả hai API. Chỉ có nội dung là khác nhau.

Bảng sau đây minh hoạ sự khác biệt giữa API Chiều sâu thô và API Độ sâu đầy đủ bằng hình ảnh một chiếc ghế và một chiếc bàn trong bếp.

API Giá trị trả về Hình ảnh camera Hình ảnh chiều sâu Hình ảnh về mức độ tin cậy
API Chiều sâu thô
  • Hình ảnh chiều sâu thô chứa số liệu ước tính độ sâu rất chính xác cho một số pixel chứ không phải tất cả pixel trong hình ảnh camera.
  • Hình ảnh tin cậy mang lại độ tin cậy cho mọi pixel hình ảnh có chiều sâu thô. Pixel hình ảnh máy ảnh không có số liệu ước tính về chiều sâu có độ tin cậy bằng 0.
API Full depth
  • Một màn "làm mượt" hình ảnh chiều sâu chứa số liệu ước tính về độ sâu cho mỗi pixel.
  • Không có hình ảnh tin cậy nào được cung cấp cùng với API này.
Không áp dụng

Hình ảnh mức độ tin cậy

Trong các hình ảnh đáng tin cậy do API Độ sâu thô trả về, pixel sáng hơn có giá trị độ tin cậy cao hơn, với các pixel trắng thể hiện độ tin cậy hoàn toàn và các pixel đen thể hiện độ tin cậy cao hơn. Nhìn chung, các vùng 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ề chiều sâu thô cao hơn so với các vùng không có nhiều hoạ tiết hơn, 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 vùng hình ảnh đủ gần máy ảnh có thể sẽ 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í điện toán của Raw depth API là khoảng một nửa chi phí điện toán cho toàn bộ depth API.

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

Với API Độ sâu thô, bạn có thể thu được hình ảnh chiều sâu cung cấp bản trình bày 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 AR, trong đó cần tăng độ chính xác và chi tiết về độ sâu cho các nhiệm vụ tìm hiểu hình học. Có thể kể đến một số trường hợp sử dụng như sau:

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

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

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

Bật tính năng Chiều sâu

Trong 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 cũng hỗ trợ depth API do những hạn chế về công suất 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ế độ chiều sâu để ứng dụng sử dụng depth API.

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

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

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ả các pixel hình ảnh được trả về qua API Chiều sâu thô sẽ chứa dữ liệu độ sâu và không phải mọi khung ARCore đều chứa hình ảnh chiều 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 chiều sâu thô sẽ dựa trên dữ liệu độ sâu mới. Nếu không, hình ảnh chiều sâu là hình ảnh chiếu lại của dữ liệu độ sâu trước đó.

Gọi frame.acquireRawDepthConfidenceImage() để lấy hình ảnh 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 chiều sâu thô. Hình ảnh mức độ tin cậy đượ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 cho biết 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