我正在使用 ARKit 和 Vision,遵循 Apple 的示例项目“通过 ARKit 实时使用视觉”。所以我不会设置相机,因为 ARKit 会帮我处理。
使用 Vision 的 VNDetectFaceRectanglesRequest,我能够取回 VNFaceObservation 对象的集合。
按照各种在线指南,我能够将 VNFaceObservation 的边界框转换为可以在 ViewController 的 UIView 上使用的边界框。
当放置在 ARKit 中的 UIView 上时,Y 轴是正确的,但 X 轴完全关闭且不准确。
// face is an instance of VNFaceObservation
let transform = CGAffineTransform(scaleX: 1, y: -1).translatedBy(x: 0, y: -view.frame.height)
let translate = CGAffineTransform.identity.scaledBy(x: view.frame.width, y: view.frame.height)
let rect = face.boundingBox.applying(translate).applying(transform)
在屏幕上(在 ARKit/UIKit 中)显示边界框以使 X 和 Y 轴与检测到的面部矩形正确匹配的正确方法是什么?我无法使用self.cameraLayer.layerRectConverted(fromMetadataOutputRect: transformedRect)
因为我没有使用 AVCaptureSession。
更新:进一步深入研究,相机的图像为 1920 x 1440。其中大部分不会显示在 ARKit 的屏幕空间上。 iPhone XS 屏幕为 375 x 812 点。
获得 Vision 的观察边界框后,我将其转换为适合当前 View (375 x 812)。这是行不通的,因为实际宽度似乎是 500(左侧和右侧超出了屏幕 View )。我该怎么办CGAffineTransform
375x812 的 CGRect 边界框(看起来像 500x812,完全猜测)?
最佳答案
这里缺少的关键部分是 ARFrame 的 displayTransform(for:viewportSize:)
。您可以阅读它的文档 here .
此函数将为给定的帧和视口(viewport)大小(显示图像和边界框的 View 的 CGRect)生成适当的变换。
func visionTransform(frame: ARFrame, viewport: CGRect) -> CGAffineTransform {
let orientation = UIApplication.shared.statusBarOrientation
let transform = frame.displayTransform(for: orientation,
viewportSize: viewport.size)
let scale = CGAffineTransform(scaleX: viewport.width,
y: viewport.height)
var t = CGAffineTransform()
if orientation.isPortrait {
t = CGAffineTransform(scaleX: -1, y: 1)
t = t.translatedBy(x: -viewport.width, y: 0)
} else if orientation.isLandscape {
t = CGAffineTransform(scaleX: 1, y: -1)
t = t.translatedBy(x: 0, y: -viewport.height)
}
return transform.concatenating(scale).concatenating(t)
}
然后您可以像这样使用它:
let transform = visionTransform(frame: yourARFrame, viewport: yourViewport)
let rect = face.boundingBox.applying(transform)
关于ios - 如何从 VNFaceObservation 边界框(Vision + ARKit)正确平移 X 轴,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54061482/