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

时间:2017-12-19 12:28:58

标签: swift scenekit arkit

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

  1. 使用ARKit估算节点位置并在世界中放置虚拟对象
  2. 使用CNN获取其估计的对象2D位置
  3. 相应地更新节点位置(以优化其在3D空间中的位置)
  4. 问题在于#2需要0.3秒左右。因此我无法使用[ { "outputFile": "assets/scss/test-page.css", "inputFile": "assets/scss/test-page.scss" } ] ,因为该点将对应于设备从#1开始的世界位置的3D点。

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

1 个答案:

答案 0 :(得分:2)

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

Unproject功能通常会做两件事:

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

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

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

    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相反,您也可以直接从projectionMatrix获取ARCamera 。因此,如果您在某个时间点抓取2D位置,那么也可以抓住相机矩阵,这样您就可以在此时向后工作3D。

    我还提到了“Z深度提示”的问题:当渲染器将3D投影到2D时,它会丢失信息(实际上是其中一个D')。因此,当您转换回3D时,您必须恢复或猜测该信息 - 传递给上述函数的screenPoint是x和y像素坐标,加上0到1之间的深度值.Zo更接近于相机,1更远。如何使用这种方式取决于算法的其余部分是如何设计的。 (至少,您可以取消投影Z = 0和Z = 1,并且您将获得3D线段的端点,原点某处沿着该线。)

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