displayTransform调用后图像方向错误

时间:2019-02-27 10:50:42

标签: swift augmented-reality arkit ciimage cvpixelbuffer

我正在尝试使用以下方法从当前ARFrame获取图像:

if let imageBuffer = sceneView.session.currentFrame?.capturedImage {
    let orientation = UIApplication.shared.statusBarOrientation
    let viewportSize = sceneView.bounds.size
    let transformation = sceneView.session.currentFrame?.displayTransform(for: orientation, viewportSize: viewportSize)

    let ciImage = CIImage(cvPixelBuffer: imageBuffer).transformed(by: transformation)
}    



对于景观来说,效果很好。对于人像,我得到了错误角度的图像(旋转了180度)。知道为什么吗?

Output:

output

Expected:

expected

2 个答案:

答案 0 :(得分:1)

  

首先,我应该说这绝对是令人不快的错误

一个问题是,当您将Portrait图像转换为ARFrame包含的图像到CIImage或CGImage时,它将失去其方向并将其逆时针旋转180度。此问题仅影响Portrait个图像。 Landscape个根本不受影响。

发生这种情况是因为Portrait图像在转换阶段没有有关其方向的信息,因此,即使将肖像图像转换为CIImage或CGImage,也仍然保持肖像模式。

要解决此问题,您应该将“标准”肖像的 width / height“非标准”肖像的 {{1} } / width,如果这些值不同,则将图像旋转至 180度(或应用方向情况.portraitUpsideDown)。

希望这会有所帮助。

答案 1 :(得分:0)

坐标系

我们需要非常清楚我们在哪个坐标系中工作。 我们知道 UIKit 的左上角有 (0,0),右上角有 (1,1),但 CoreImage 不是这样:

<块引用>

由于 Core Image 的坐标系与 UIKit 不匹配...(参见 here

或 Vision(包括 CoreML 识别):

<块引用>

Vision 使用从 0.0 到 1.0 的标准化坐标空间 左原点。 (见here

然而,displayTransform 使用 UIKit 方向:

<块引用>

从归一化图像坐标转换的变换矩阵 捕获的图像到归一化的图像坐标,说明 指定的参数。归一化图像坐标范围从 图像左上角的 (0,0) 到下角的 (1,1) 右上角。 (见here

因此,如果您将 CVPixelBuffer 加载到 CIImage 中,然后尝试应用 displayTransform 矩阵,它将被翻转(如您所见)。 但是,它也会弄乱图像。

显示转换的作用

显示变换似乎主要用于 Metal 或其他倾向于匹配核心图像方向的较低级别的绘图程序。 变换会缩放图像并移动它,使其在指定的边界内“填充”。

如果您要在 UIImageView 中显示图像,那么它将被颠倒,因为它们的方向不同。但此外,图像视图会为您执行方面填充转换, 所以没有理由移动或缩放,因此根本没有理由使用 displayTransform。只需将图像旋转到正确的方向即可。

// apply an orientation. You can easily make a function
// which converts the screen orientation to this parameter

let rotated = CIImage(cvPixelBuffer: frame.capturedImage).oriented(...)
imageView.image = UIImage(ciImage: rotated)

如果您想在图像上叠加内容,例如通过向 UIImageView 添加子视图,那么 displayTransform 会很有帮助。 它会将图像坐标(在 UIKit 方向上)转换为图像视图中的坐标 与显示的图像对齐(由于纵横比填充而移动和缩放)。