如何在SpriteKit坐标系中计算ARKit 1.5识别的图像尺寸?
解决ARKit+SpriteKit中参考图像尺寸转换的问题
嘿,我明白你卡在这儿的点了——ARKit的物理尺寸和SpriteKit的像素坐标系确实是个容易搞混的地方,而且刚检测图像时那些frame属性没值也挺让人头疼的。我来一步步给你拆解怎么解决这个问题:
为什么frame和calculateAccumulatedFrame是0?
刚检测到图像的前几帧里,ARKit还在确认图像的精确位置和姿态,这时候它还没完成屏幕投影的计算,所以这两个属性会返回空的CGRect。不用死等它们有值,我们可以用physicalSize自己算出SpriteKit里的尺寸。
用physicalSize计算SpriteKit中的图像尺寸
核心思路是把参考图像的现实物理尺寸(米),通过ARKit的坐标转换,映射到SpriteKit的像素坐标系里。具体可以通过转换图像四个角的坐标来实现:
步骤1:获取图像的物理尺寸和世界坐标点
首先拿到检测到的图像锚点,以及它的物理尺寸,然后计算图像四个角在世界坐标系中的位置(锚点的原点在图像中心):
guard let imageAnchor = anchor as? ARImageAnchor else { return } let realWorldSize = imageAnchor.referenceImage.physicalSize // 图像四个角相对于锚点原点的本地坐标 let topLeft = simd_float3(-realWorldSize.width/2, realWorldSize.height/2, 0) let bottomRight = simd_float3(realWorldSize.width/2, -realWorldSize.height/2, 0) // 转换为世界坐标系(锚点的transform包含了图像在现实中的位置和姿态) let worldTopLeft = simd_mul(imageAnchor.transform, simd_float4(topLeft, 1)).xyz let worldBottomRight = simd_mul(imageAnchor.transform, simd_float4(bottomRight, 1)).xyz
步骤2:将世界坐标转换为SpriteKit屏幕坐标
用ARKit视图的projectPoint方法,把世界坐标转换成屏幕上的像素坐标(SpriteKit用的是UIKit坐标系,原点在左上角):
guard let currentFrame = session.currentFrame, let arView = view as? ARSKView else { return } // 转换为屏幕坐标 let screenTopLeft = arView.projectPoint(SCNVector3(worldTopLeft)) let screenBottomRight = arView.projectPoint(SCNVector3(worldBottomRight))
步骤3:计算SpriteKit中的图像尺寸
通过两个对角点的坐标差,就能得到图像在SpriteKit中的像素宽高:
let spriteKitWidth = abs(screenBottomRight.x - screenTopLeft.x) let spriteKitHeight = abs(screenBottomRight.y - screenTopLeft.y) // 现在你可以用这个尺寸创建SpriteKit节点了 let imageNode = SKSpriteNode(color: .red, size: CGSize(width: spriteKitWidth, height: spriteKitHeight)) imageNode.position = CGPoint(x: (screenTopLeft.x + screenBottomRight.x)/2, y: (screenTopLeft.y + screenBottomRight.y)/2) scene?.addChild(imageNode)
额外提示
- 如果需要更精准的结果,可以转换四个角的坐标,然后计算最小包围矩形的尺寸,避免因为图像倾斜导致的误差。
- 当ARKit稳定跟踪图像后,
frame属性会自动填充有效值,这时候你也可以用它来验证自己计算的结果是否正确。
内容的提问来源于stack exchange,提问作者congpc87
相关产品推荐
相关产品推荐

