将ARFrame的捕获图像转换为UIImage方向问题

Alo*_*edi 4 uiimage ios swift cvpixelbuffer arkit

我想检测球并让AR模型与它互动.我使用opencv进行球检测并发送我可用于hitTest获取坐标的球的中心sceneView.我一直CVPixelBufferUIImage使用以下功能:

static func convertToUIImage(buffer: CVPixelBuffer) -> UIImage?{
    let ciImage = CIImage(cvPixelBuffer: buffer)
    let temporaryContext = CIContext(options: nil)
    if let temporaryImage = temporaryContext.createCGImage(ciImage, from: CGRect(x: 0, y: 0, width: CVPixelBufferGetWidth(buffer), height: CVPixelBufferGetHeight(buffer)))
    {
        let capturedImage = UIImage(cgImage: temporaryImage)
        return capturedImage
    }
    return nil
}
Run Code Online (Sandbox Code Playgroud)

这给了我旋转的图像:

在此输入图像描述

然后我发现使用以下方法改变方向:

let capturedImage = UIImage(cgImage: temporaryImage, scale: 1.0, orientation: .right)
Run Code Online (Sandbox Code Playgroud)

虽然它在设备处于纵向时给出了正确的方向,但是将设备旋转到横向再次给出了旋转图像.

现在我正在考虑使用它来处理它viewWillTransition.但在此之前,我想知道:

  1. 如果还有其他方法来转换正确方向的图像?
  2. 为什么会这样?

And*_*ini 8

1.有没有其他方法可以正确的方向转换图像?

您可以尝试使用snapshot()ARSCNView(从继承SCNView),其中:

绘制视图的内容并将其作为新图像对象返回

所以,如果你有一个像这样的对象:

@IBOutlet var arkitSceneView:ARSCNView!
Run Code Online (Sandbox Code Playgroud)

你只需要这样做:

let imageFromArkitScene:UIImage? = arkitSceneView.snapshot()
Run Code Online (Sandbox Code Playgroud)

2.为什么会这样?

这是因为CVPixelBuffer它来自ARFrame,这是:

通过正在运行的AR会话从设备摄像头捕获(连续).

好吧,由于相机方向不会随着设备的旋转而变化(它们是分开的),为了能够将框架的方向调整到当前视图,您应该重新定位从相机拍摄的图像应用仿射变换提取displayTransform(for:viewportSize:):

返回仿射变换,用于在标准化图像坐标和适合于在屏幕上渲染摄像机图像的坐标空间之间进行转换.

您可以在这里找到好的文档,用法示例:

let orient = UIApplication.shared.statusBarOrientation
let viewportSize = yourSceneView.bounds.size
let transform = frame.displayTransform(for: orient, viewportSize: viewportSize).inverted()
var finalImage = CIImage(cvPixelBuffer: pixelBuffer).transformed(by: transform)
Run Code Online (Sandbox Code Playgroud)