【问题标题】:Save the depth data with UIImageWriteToSavedPhotosAlbum使用 UIImageWriteToSavedPhotosAlbum 保存深度数据
【发布时间】:2021-06-12 04:22:52
【问题描述】:

我在新 iPhone 设备上使用 ARKit 4 (+MetalKit),我正在尝试访问深度数据(来自 LiDAR)并将其与实际 RGB 图像一起保存为深度图。虽然我看过很多演示,但没有显示实际可视化深度图的代码。我制作了一个按钮,这是与它一起使用的代码:

func saveCapturedBuffer(buffer: CVPixelBuffer) {
    let depthCIImage = CIImage(cvPixelBuffer: buffer)
    let context: CIContext = CIContext.init(options: nil)
    let depthCGImage: CGImage = context.createCGImage(depthCIImage, from: depthCIImage.extent)!
    let depthUIImage = UIImage.init(cgImage: depthCGImage)
    UIImageWriteToSavedPhotosAlbum(depthUIImage, self, #selector(saveError), nil)
    }

@objc func capture(sender: UIButton) {
    let frame: ARFrame = session.currentFrame!
    guard let depthData =  frame.sceneDepth ?? frame.sceneDepth else { return }
    var pixelBufferDepth: CVPixelBuffer!
    pixelBufferDepth = depthData.depthMap
    saveCapturedBuffer(buffer: pixelBufferDepth)
    
    var capturedImageBuffer: CVPixelBuffer!
    capturedImageBuffer = frame.capturedImage
    print(CVPixelBufferGetPlaneCount(capturedImageBuffer))
    saveCapturedBuffer(buffer: capturedImageBuffer)
}

@objc func saveError(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
    if let error = error {
        print("error: \(error.localizedDescription)")
    } else { }
}

因此,此代码保存 RGB 图像没有任何问题。但是,深度图有时绝对是空的(而我在渲染深度图时会看到更好的深度图)。所以,我猜CVPixelBuffer-to-UIImage 转换有问题。我对 Swift 完全陌生,我不知道它会是什么。

我发现CVPixelBuffer 是非平面的,所以我猜这是我的问题,但我不知道该怎么做,也没有找到任何解释如何继续的答案。

那么,如何正确地将非平面CVPixelBuffersceneDepth.depthMap 转换为UIImage

【问题讨论】:

    标签: swift uiimage cvpixelbuffer


    【解决方案1】:

    https://developer.apple.com/documentation/realitykit/taking_pictures_for_3d_object_capture

    从苹果的示例代码中,苹果使用CGColorSpace.linearGray来保存depthData

        func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto,
                     error: Error?) {
        photoProcessingHandler(false)
        
        if let error = error {
            print("Error capturing photo: \(error)")
            photoData = nil
        } else {
            // Cache the HEIF representation of the data.
            photoData = photo
        }
        
        // Cache the depth data, if it exists, as a disparity map.
        // logger.log("DidFinishProcessingPhoto: photo=\(String(describing: photo))")
        if let depthData = photo.depthData?.converting(toDepthDataType:
                                                        kCVPixelFormatType_DisparityFloat32),
           let colorSpace = CGColorSpace(name: CGColorSpace.linearGray) {
            let depthImage = CIImage( cvImageBuffer: depthData.depthDataMap,
                                      options: [ .auxiliaryDisparity: true ] )
            depthMapData = context.tiffRepresentation(of: depthImage,
                                                      format: .Lf,
                                                      colorSpace: colorSpace,
                                                      options: [.disparityImage: depthImage])
        } else {
            logger.error("colorSpace .linearGray not available... can't save depth data!")
            depthMapData = nil
        }
    }
    

    也许您可以尝试一下,将您的代码从 RGB 更改为 linearGray,然后您可以下载并运行演示,捕获图像并进行比较。

    我还尝试使用 linearGray 来捕获基于 AVFoundation 的图像,我发现超过 2 米的距离可能会导致白色 .tiff 图像。

    Apple 说 LiDAR 可以工作最远 5 米,我认为这个距离可能受到光线或物体材料的某种影响。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-07
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-21
      相关资源
      最近更新 更多