【问题标题】:SceneKit point cloud from ARKit depth buffers来自 ARKit 深度缓冲区的 SceneKit 点云
【发布时间】:2021-06-16 16:34:30
【问题描述】:

我试图在 SceneKit 中找到一种简单的方法来计算 SceneKit 和 LiDAR 数据中像素的深度 sceneView.session.currentFrame?.smoothedSceneDepth?.depthMap

理想情况下,我不想使用金属着色器。我希望在我的currentFrame 及其对应的深度图中找到一个点,以获取 SceneKit 中点的深度(理想情况下在世界坐标中,而不仅仅是在那个时间点的那个截锥体的本地)。

不需要快速性能,因为它不会在捕获时计算。

我知道link 的 Apple 项目,但这对于我的需求来说太复杂了。

作为一个起点,我的代码是这样工作的:

    
guard let depthData = frame.sceneDepth else { return }
let camera = frame.camera
        
let depthPixelBuffer = depthData.depthMap
let depthHeight = CVPixelBufferGetHeight(depthPixelBuffer)
let depthWidth  = CVPixelBufferGetWidth(depthPixelBuffer)
let resizeScale = CGFloat(depthWidth) / CGFloat(CVPixelBufferGetWidth(frame.capturedImage))
let resizedColorImage = frame.capturedImage.toCGImage(scale: resizeScale);
guard let colorData = resizedColorImage.pixelData() else {
    fatalError()
}

var intrinsics = camera.intrinsics;
let referenceDimensions = camera.imageResolution;
let ratio = Float(referenceDimensions.width) / Float(depthWidth)

intrinsics.columns.0[0] /= ratio
intrinsics.columns.1[1] /= ratio
intrinsics.columns.2[0] /= ratio
intrinsics.columns.2[1] /= ratio

var points: [SCNVector3] = []

let depthValues = depthPixelBuffer.depthValues()

for vv in 0..<depthHeight {
    for uu in 0..<depthWidth {
        let z = -depthValues[uu + vv * depthWidth]
        let x = Float32(uu) / Float32(depthWidth) * 2.0 - 1.0;
        let y = 1.0 - Float32(vv) / Float32(depthHeight) * 2.0;
        points.append(SCNVector3(x, y, z))
    }
}

生成的点云看起来不错,但在 Z 轴上严重弯曲。我意识到这段代码也没有调整屏幕方向。

【问题讨论】:

    标签: scenekit arkit lidar


    【解决方案1】:

    A Cupertino 在 developer.apple.com 的论坛上回复了我:

    无论是在 CPU 端还是 GPU 端,反投影计算本身都是相同的。

    CPU 方面,计算如下所示:

    /// Returns a world space position given a point in the camera image, the eye space depth (sampled/read from the corresponding point in the depth image), the inverse camera intrinsics, and the inverse view matrix.
    
    func worldPoint(cameraPoint: SIMD2<Float>, eyeDepth: Float, cameraIntrinsicsInversed: simd_float3x3, viewMatrixInversed: simd_float4x4) -> SIMD3<Float> {
            let localPoint = cameraIntrinsicsInversed * simd_float3(cameraPoint, 1) * -eyeDepth
            let worldPoint = viewMatrixInversed * simd_float4(localPoint, 1);
            return (worldPoint / worldPoint.w)[SIMD3(0,1,2)];
     }
    

    实现了,这个样子

    for vv in 0..<depthHeight {
        for uu in 0..<depthWidth {
            let z = -depthValues[uu + vv * depthWidth]
            let viewMatInverted = (sceneView.session.currentFrame?.camera.viewMatrix(for: UIApplication.shared.statusBarOrientation))!.inverse
            let worldPoint = worldPoint(cameraPoint: SIMD2(Float(uu), Float(vv)), eyeDepth: z, cameraIntrinsicsInversed: intrinsics.inverse, viewMatrixInversed: viewMatInverted * rotateToARCamera )
            points.append(SCNVector3(worldPoint))
        }
    }
    

    点云非常混乱,需要确定信心,并且在发生 Int 舍入的地方存在垂直间隙,但这是一个可靠的开始。缺少的功能来自上述问题中 Apple 演示项目的链接。

    【讨论】:

      猜你喜欢
      • 2017-03-21
      • 1970-01-01
      • 2015-04-15
      • 1970-01-01
      • 1970-01-01
      • 2016-09-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-12
      相关资源
      最近更新 更多