2

我正在使用 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 的观察边界框后,我将其转换为适合当前视图 (375 x 812)。这不起作用,因为实际宽度似乎是 500(左侧和右侧不在屏幕视图中)。我如何CGAffineTransform从 375x812 获得 CGRect 边界框(看起来像 500x812,总猜测)?

4

1 回答 1

4

这里缺少的关键部分是 ARFrame 的displayTransform(for:viewportSize:). 你可以在这里阅读它的文档。

此函数将为给定的框架和视口大小(您在其中显示图像和边界框的视图的 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)
于 2019-02-13T12:41:49.397 回答