Project Point 方法:将 rawFeaturePoint 转换为 Screen Space

Posted

技术标签:

【中文标题】Project Point 方法:将 rawFeaturePoint 转换为 Screen Space【英文标题】:Project Point method: converting rawFeaturePoint to Screen Space 【发布时间】:2022-01-15 10:02:00 【问题描述】:

大家好,我想了解使用 ARKit 的 projectPoint 函数时返回给我的值。

我的目标是采取一个点p = (x,y,z),其中元组中的所有值都在[-1, 1] 范围内,并将其转换为p' = (x',y'),其中该对中的所有值都在[0,1] 范围内,即项目来自世界空间到屏幕/图像空间。

我知道arframe.camera.imageResolution = (1920.0, 1440.0),并且 我知道我的屏幕尺寸是(390.0 ,844.0)

所以,当我使用我写的函数时:arframe.camera.projectPoint(point: p, orientation: .portrait, viewportSize: arframe.camera.imageResolution

这会返回(x, y),但有时会出现x > 1440.0y > 1920.0。 此外,有时xy 是负值。

我对函数如何返回大于我们给出的视口大小的值感到困惑。我也对为什么这些值本身是负数感到困惑。

Apple 提供的文档说明该函数“将点从 ARKit 检测到的 3D 世界空间的投影返回到渲染场景的视图的 2D 空间。”

“渲染场景的二维空间”是什么意思?

【问题讨论】:

【参考方案1】:

理论

func projectPoint(_ point: simd_float3, 
              orientation: UIInterfaceOrientation, 
             viewportSize: CGSize) -> CGPoint

Xcode小技巧说——实例方法projectPoint(...)返回指定点投影到原点在左上角且大小与viewportSize参数一致的2D像素坐标空间。

Screen SizeViewport size 之间的区别描述为 HereHere(我看到你说你知道这一点)。

解决方案

诀窍在于,只有当 3D 点在相机的frustum 的覆盖范围内时,才能正确投影 2D 点——根据勾股定理计算距离并不是什么秘密。 .

import ARKit
 
extension ViewController: ARSessionDelegate 
    
    func session(_ session: ARSession, didUpdate frame: ARFrame) 
        
        let point = simd_float3(0.3, 0.5,-2.0)
        
        if self.sceneView.isNode(self.sphere,
                             insideFrustumOf: self.sceneView.pointOfView!) 
            
            let pp = frame.camera.projectPoint(point,
                                  orientation: .portrait,
                                 viewportSize: CGSize(width: 375, height: 812))

            self.label_A.text = String(format: "%.2f", pp.x / 375)
            self.label_B.text = String(format: "%.2f", pp.y / 812)
        
    

如您所见,输出归一化坐标(0.00 ... 1.00)的值非常简单:

class ViewController: UIViewController 

    @IBOutlet var sceneView: ARSCNView!
    @IBOutlet var label_A: UILabel!
    @IBOutlet var label_B: UILabel!
    let sphere = SCNNode(geometry: SCNSphere(radius: 0.1))
    
    override func viewDidLoad() 
        super.viewDidLoad()

        sceneView.session.delegate = self
        sceneView.scene = SCNScene()
        
        sphere.geometry?.firstMaterial?.diffuse.contents = UIColor.green
        sphere.position = SCNVector3(0.3, 0.5,-2.0)
        sceneView.scene.rootNode.addChildNode(sphere)
        
        let config = ARWorldTrackingConfiguration()
        sceneView.session.run(config)
    

我使用了 iPhone X 参数——垂直 viewportSize 为 375 x 812。

【讨论】:

嗨,安迪,感谢您的回复。但是,我没有使用SCNScene,因此我无法轻松检查p 是否在相机的未来主义范围内。相反,您认为我可以根据值过滤点吗,v,返回的projectPoint() 函数,即如果0 < v.x < screenWidth0 < v.y < screenHeight,那么我知道p 在相机的未来主义中。跨度> 嗨,尼古拉斯。您没有明确指出您使用的是哪个渲染框架,所以我得出结论是 ARKIt + SceneKit。 这是一个很棒的资源,包含平面提取的数学 - web.archive.org/web/20120531231005/http://crazyjoke.free.fr/doc/…

以上是关于Project Point 方法:将 rawFeaturePoint 转换为 Screen Space的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 PIL Image.point(table) 方法将阈值应用于 256 灰度图像?

Halcon - 将坐标转移到不同的平面

在 python vs st_project 中计算一个点

在 three.js 中将 Point3D 转换为 Screen2D 得到错误结果

有没有办法将vector<Point2f> 转换为vector<Keypoint>?

点对点协议(Point-to-Point Protocol)