在iOS中从Vuforia返回的Pose获取目标的2D屏幕坐标
在iOS平台通过Vuforia Pose计算目标2D屏幕坐标
核心思路
无需深入矩阵数学,直接利用Vuforia提供的ModelViewProjection(MVP)矩阵,将目标的3D局部坐标转换为屏幕2D坐标,步骤分为:矩阵变换、透视除法、屏幕坐标映射。
实现代码
以下是Swift和Objective-C的可直接复用代码,需在Vuforia的追踪回调中执行:
Swift 版本
func didTrackablePoseUpdated(_ trackableResult: TrackableResult, state: TrackableBehaviour.Status) { guard state == .tracked else { return } // 1. 获取Vuforia返回的MVP矩阵并转为SIMD矩阵 let mvpRawArray = trackableResult.pose.modelViewProjectionMatrix let mvpMatrix = float4x4(mvpRawArray) // 2. 定义目标的3D局部坐标(示例为目标中心,可替换为目标上任意点) let target3DPoint = SIMD3<Float>(0, 0, 0) // 3. 转为齐次坐标并执行矩阵变换 let homogeneousPoint = SIMD4<Float>(target3DPoint.x, target3DPoint.y, target3DPoint.z, 1.0) let transformedPoint = mvpMatrix * homogeneousPoint // 4. 透视除法得到NDC空间坐标(范围[-1,1]) let ndcX = transformedPoint.x / transformedPoint.w let ndcY = transformedPoint.y / transformedPoint.w // 5. 映射为iOS屏幕坐标(左上角为原点) let screenBounds = UIScreen.main.bounds let screenX = (ndcX + 1.0) * screenBounds.width / 2.0 let screenY = (1.0 - ndcY) * screenBounds.height / 2.0 // 最终屏幕坐标可直接使用 print("目标屏幕坐标:(\(screenX), \(screenY))") }
Objective-C 版本
- (void)didTrackablePoseUpdated:(VuforiaTrackableResult *)trackableResult state:(VuforiaTrackableBehaviourStatus)state { if (state != VuforiaTrackableBehaviourStatusTracked) return; // 1. 获取MVP矩阵并构造4x4矩阵(列主序,匹配Vuforia返回格式) const float* mvpRawArray = trackableResult.pose.modelViewProjectionMatrix; matrix_float4x4 mvpMatrix = { .columns = { {mvpRawArray[0], mvpRawArray[1], mvpRawArray[2], mvpRawArray[3]}, {mvpRawArray[4], mvpRawArray[5], mvpRawArray[6], mvpRawArray[7]}, {mvpRawArray[8], mvpRawArray[9], mvpRawArray[10], mvpRawArray[11]}, {mvpRawArray[12], mvpRawArray[13], mvpRawArray[14], mvpRawArray[15]} } }; // 2. 目标3D局部坐标(示例为中心) vector_float3 target3DPoint = {0.0f, 0.0f, 0.0f}; vector_float4 homogeneousPoint = {target3DPoint.x, target3DPoint.y, target3DPoint.z, 1.0f}; // 3. 矩阵变换 vector_float4 transformedPoint = matrix_multiply(mvpMatrix, homogeneousPoint); // 4. 透视除法 float ndcX = transformedPoint.x / transformedPoint.w; float ndcY = transformedPoint.y / transformedPoint.w; // 5. 转换为屏幕坐标 CGRect screenBounds = [UIScreen mainScreen].bounds; CGFloat screenX = (ndcX + 1.0f) * CGRectGetWidth(screenBounds) / 2.0f; CGFloat screenY = (1.0f - ndcY) * CGRectGetHeight(screenBounds) / 2.0f; NSLog(@"目标屏幕坐标:(%f, %f)", screenX, screenY); }
注意事项
- 自定义目标点:如果需要目标上的特定点(如右上角),只需替换
target3DPoint为目标局部坐标系中的对应坐标(例如目标尺寸为1×1×0时,右上角为(0.5, 0.5, 0))。 - 矩阵顺序:Vuforia返回的矩阵是列主序,代码中已正确处理,无需额外调整。
- 坐标系适配:iOS屏幕原点在左上角,而NDC空间y轴向上,因此用
1.0 - ndcY完成y轴翻转。
内容的提问来源于stack exchange,提问作者Macro
相关产品推荐
相关产品推荐

