首页 文章

ARKit项目点与之前的设备位置

提问于
浏览
1

我正在将ARKit与CNN结合起来,以便在它们漂移时不断更新ARKit节点 . 所以:

  • 使用ARKit估算节点位置并在世界中放置虚拟对象

  • 使用CNN获取其估计的对象2D位置

  • 相应地更新节点位置(以优化其在3D空间中的位置)

问题是#2需要0.3秒左右 . 因此我不能使用 sceneView.unprojectPoint 因为该点将对应于来自设备#1的世界位置的3D点 .

如何计算从旧位置到CNN 2D点的3D矢量?

1 回答

  • 1

    unprojectPoint 只是一个矩阵数学便利函数,类似于许多面向图形的库(如DirectX,旧式OpenGL,Three.js等)中的函数 . 在SceneKit中,它作为视图的方法提供,这意味着它使用模型/视图/投影矩阵和视口当前用于渲染的视图进行操作 . 但是,如果您知道该功能的工作原理,您可以自己实现它 .

    Unproject函数通常会做两件事:

    • 将视口坐标(像素)转换为剪辑空间坐标系(所有方向的-1.0到1.0) .

    • 反转投影变换(假设剪辑空间中有一些任意Z值)和视图(相机)变换以获得3D世界空间坐标 .

    鉴于这些知识,我们可以 Build 自己的功能 . (警告:未经测试 . )

    func unproject(screenPoint: float3, // see below for Z depth hint discussion
                     modelView: float4x4,
                    projection: float4x4,
                      viewport: CGRect) -> float3 {
    
        // viewport to clip: subtract viewport origin, divide by size, 
        // scale/offset from 0...1 to -1...1 coordinate space
        let clip = (screenPoint - float3(viewport.x, viewport.y, 1.0))
                   / float3(viewport.width, viewport.height, 1.0)
                   * float3(2) - float3(1)
        // apply the reverse of the model-view-projection transform
        let inversePM = (projection * modelView).inverse
        let result = inversePM * float4(clip.x, clip.y, clip.z, 1.0)
        return float3(result.x, result.y, result.z) / result.w // perspective divide
    }
    

    现在,使用它...你传递给这个函数的 modelView 矩阵是 ARCamera.transform 的反函数,你也可以直接从 ARCamera 得到 projectionMatrix . 因此,如果您在某个时间点抓取2D位置,那么也可以 grab 相机矩阵,这样您就可以在此时向后工作3D .

    实际上有's still the issue of that 265268 I mentioned: when the renderer projects 3D to 2D it loses information (one of those D' s . 因此,当您转换回3D时,您必须恢复或猜测该信息 - 您传入上述函数的 screenPoint 是x和y像素坐标,加上0到1之间的深度值 . 零距离相机更近,1离得更远了 . 如何使用这种方式取决于算法的其余部分是如何设计的 . (至少,您可以取消投影Z = 0和Z = 1,并且您将获得3D线段的 endpoints ,原始点位于该线的某个位置 . )

    当然,这是否可以与你的新颖的基于CNN的方法实际上放在一起完全是另一个问题 . 但至少你学到了一些有用的3D图形数学!

相关问题