Android开发求助:如何将ARCore 3D坐标系转换为2D屏幕坐标?
ARCore 3D Node与TFLite 2D物体碰撞检测实现方案
核心思路
要实现碰撞检测,关键是将ARCore中3D Node的世界坐标转换为Android屏幕的2D坐标,再与TensorFlow Lite(TFLite)检测到的2D物体边界框做区域重叠判断。
具体实现步骤
获取Node的世界空间坐标
ARCore的Node在场景中有自己的局部坐标,需通过worldPose获取其世界空间下的位置,避免父节点层级带来的坐标偏移:// 假设targetNode是你要检测的AR Node val worldPosition = FloatArray(3) targetNode.worldPose.getTranslation(worldPosition, 0)3D坐标转2D屏幕坐标
直接利用ArSceneView封装的worldToScreenPoint方法完成转换,该方法会自动处理相机投影矩阵和屏幕坐标系转换:val worldPoint = Vector3(worldPosition[0], worldPosition[1], worldPosition[2]) val screenPoint = arSceneView.worldToScreenPoint(worldPoint) // screenPoint.x/y 对应Android屏幕坐标系(左上角为原点,x向右递增,y向下递增)若需要手动处理投影(比如自定义相机逻辑),可以用ARCore Camera的
projectPoint方法:val frame = arSceneView.arFrame ?: return val camera = frame.camera val screenCoords = FloatArray(2) // 第三个参数是相机的近平面偏移,一般传0即可 val isVisible = camera.projectPoint(screenCoords, 0, 0, worldPosition[0], worldPosition[1], worldPosition[2]) // isVisible为true表示该3D点在相机视锥体内,转换后的坐标有效 if (isVisible) { // 若测试后发现y轴方向反转,可调整:val adjustedY = arSceneView.height - screenCoords[1] }TFLite检测结果适配屏幕坐标
TFLite的检测结果通常基于输入图像的尺寸,需将其缩放为屏幕尺寸下的坐标:// 假设TFLite输入图像尺寸为inputWidth x inputHeight val inputWidth = 224 // 根据你的TFLite模型输入调整 val inputHeight = 224 val screenWidth = arSceneView.width.toFloat() val screenHeight = arSceneView.height.toFloat() // 计算缩放比例 val scaleX = screenWidth / inputWidth val scaleY = screenHeight / inputHeight // 从TFLite检测结果中获取原始边界框(left, top, right, bottom) val tfliteRawBox = floatArrayOf(...) // 缩放为屏幕坐标下的边界框 val scaledBox = floatArrayOf( tfliteRawBox[0] * scaleX, tfliteRawBox[1] * scaleY, tfliteRawBox[2] * scaleX, tfliteRawBox[3] * scaleY )碰撞判断
检查转换后的2D屏幕点是否在TFLite缩放后的边界框内:val isCollided = screenPoint.x >= scaledBox[0] && screenPoint.x <= scaledBox[2] && screenPoint.y >= scaledBox[1] && screenPoint.y <= scaledBox[3] if (isCollided) { // 执行碰撞后的逻辑(比如弹窗、Node变色等) }
关键注意事项
- 实时性处理:如果Node是动态移动的,需在
onUpdateFrame回调或SceneView的每一帧更新中执行转换和检测,保证碰撞判断的实时性。 - 可见性判断:使用
camera.projectPoint时,需通过返回的isVisible判断点是否在相机视野内,避免无效的坐标判断。 - 坐标系统对齐:确认TFLite输入图像的方向与屏幕方向一致(比如是否做了旋转处理),否则需额外调整边界框的坐标。
内容的提问来源于stack exchange,提问作者Fatih POLAT
相关产品推荐
相关产品推荐

