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.0
和y > 1920.0
。
此外,有时x
和y
是负值。
我对函数如何返回大于我们给出的视口大小的值感到困惑。我也对为什么这些值本身是负数感到困惑。
Apple 提供的文档说明该函数“将点从 ARKit 检测到的 3D 世界空间的投影返回到渲染场景的视图的 2D 空间。”
“渲染场景的二维空间”是什么意思?
【问题讨论】:
【参考方案1】:理论
func projectPoint(_ point: simd_float3,
orientation: UIInterfaceOrientation,
viewportSize: CGSize) -> CGPoint
Xcode小技巧说——实例方法
projectPoint(...)
返回指定点投影到原点在左上角且大小与viewportSize参数一致的2D像素坐标空间。
Screen Size
和 Viewport size
之间的区别描述为 Here 和 Here(我看到你说你知道这一点)。
解决方案
诀窍在于,只有当 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 < screenWidth
和0 < 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 灰度图像?
在 three.js 中将 Point3D 转换为 Screen2D 得到错误结果