在苹果的示例项目“在ARKit中实时使用视觉”之后,我同时使用了ARKit和Vision。因此,我不会设置相机,因为ARKit会为我处理。
使用Vision的VNDetectFaceRectanglesRequest,我可以取回VNFaceObservation对象的集合。
通过在线阅读各种指南,我可以将VNFaceObservation的boundingBox转换为可以在ViewController的UIView上使用的边界框。
将Y轴放在ARKit中的UIView上时是正确的,但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中)显示boundingBox以便X和Y轴正确匹配检测到的脸部矩形的正确方法是什么?我没有使用self.cameraLayer.layerRectConverted(fromMetadataOutputRect: transformedRect)
,因为我没有使用AVCaptureSession。
更新:进一步研究,摄像机的图像为1920 x1440。大多数图像未显示在ARKit的屏幕空间上。 iPhone XS屏幕为375 x 812点。
获得Vision的观察包围盒后,我对其进行了转换以适合当前视图(375 x 812)。由于实际宽度似乎为500(左右两侧不在屏幕视图中),因此无法使用。我该如何CGAffineTransform
从375x812的CGRect边界框(似乎总猜测为500x812)?
答案 0 :(得分:2)
此处缺少的关键部分是ARFrame的displayTransform(for:viewportSize:)
。您可以阅读here的文档。
此功能将为给定的帧和视口大小(在其中显示图像和边界框的视图的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)