iOS基于CoreML获取检测目标2D中心点坐标及3D坐标转换问询
获取检测目标2D中心点坐标(用于Raycast转3D)
我明白你现在的处境——已经用Custom Vision训练好CoreML模型,导入Xcode用Vision框架跑起来能识别目标、拿到概率,但卡在了获取检测目标的2D中心点坐标上。别担心,这其实是Vision框架里的一个常见细节问题,我来一步步帮你解决:
核心原理:Vision检测结果的坐标处理
Vision框架返回的VNDetectedObjectObservation对象里,包含了检测目标的boundingBox属性,但这个属性是归一化的CGRect(坐标值在0-1之间),而且它的坐标系是以图像的左下角为原点的,和UIKit常用的左上角原点坐标系不一样,所以需要做两步转换:归一化转实际尺寸、坐标系原点转换。
具体实现步骤&代码示例
在你的Vision请求完成回调里,添加以下逻辑来计算中心点:
func processDetectionResults(request: VNRequest, error: Error?) { // 确保结果是目标检测类型 guard let detections = request.results as? [VNDetectedObjectObservation] else { print("未检测到目标") return } for detection in detections { // 1. 获取归一化的边界框 let normalizedBox = detection.boundingBox // 2. 替换成你的实际图像/视图尺寸(比如ARView的size、UIImageView的bounds.size) let targetSize = CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height) // 3. 转换坐标系:Vision(左下原点)→ UIKit(左上原点) let adjustedY = targetSize.height - normalizedBox.origin.y - normalizedBox.size.height let actualBoundingBox = CGRect( x: normalizedBox.origin.x * targetSize.width, y: adjustedY, width: normalizedBox.size.width * targetSize.width, height: normalizedBox.size.height * targetSize.height ) // 4. 计算中心点坐标 let centerPoint = CGPoint( x: actualBoundingBox.midX, y: actualBoundingBox.midY ) // 到这里你就拿到了目标的2D中心点坐标! print("目标中心点:\(centerPoint)") // 5. 用这个坐标做Raycast获取3D坐标(比如ARKit场景) if let arView = self.view as? ARView { let raycastQuery = arView.raycastQuery(from: centerPoint, allowing: .estimatedPlane, alignment: .horizontal) if let result = arView.session.raycast(raycastQuery).first { let worldPosition = result.worldTransform.columns.3 print("目标对应的3D坐标:\(worldPosition)") } } } }
关键注意事项
- 尺寸匹配:
targetSize必须是你用来做检测的图像/视图的实际尺寸,如果是ARKit的ARView,直接用arView.bounds.size就可以;如果是UIImageView,要用imageView.image?.size或者imageView.bounds.size(根据你是否缩放图像)。 - 坐标系转换:这一步很容易踩坑!如果跳过Y轴的调整,你拿到的Y坐标会是反向的,导致中心点位置错误。
- Raycast适配:如果是在ARKit中,直接用屏幕坐标的
centerPoint调用raycastQuery就能生成对应的3D射线,进而得到空间中的3D坐标。
内容的提问来源于stack exchange,提问作者Venkatesh
相关产品推荐
相关产品推荐

