5

我想在渲染时应用相机滤镜,我的代码是......

func session(_ session: ARSession, didUpdate frame: ARFrame) {
let image = CIImage(cvPixelBuffer: frame.capturedImage)
        var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0

        color.getRed(&r, green: &g, blue: &b, alpha: &a)
        filter.setDefaults()
        filter.setValue(image, forKey: kCIInputImageKey)
        filter.setValue(CIVector(x: r, y: 0, z: 0, w: 0), forKey: "inputRVector")
        filter.setValue(CIVector(x: 0, y: g, z: 0, w: 0), forKey: "inputGVector")
        filter.setValue(CIVector(x: 0, y: 0, z: b, w: 0), forKey: "inputBVector")
        filter.setValue(CIVector(x: 0, y: 0, z: 0, w: a), forKey: "inputAVector")

        if let result = filter.outputImage,
            let cgImage = context.createCGImage(result, from: result.extent) {
            sceneView.scene.background.contents = cgImage
            sceneView.scene.background.contentsTransform = SCNMatrix4MakeRotation(.pi / 2, 0, 0, 1)
        }
}

在运行时,输出会被拉伸。我附上了两张图片,

  1. 普通相机渲染
  2. 带滤镜相机渲染。

这是正常的相机渲染,看起来不错,

这是带滤镜的实时摄像机,您可以在运行时看到实时摄像机被拉伸。

请帮我解决它,如果您提供任何演示代码或项目将有很大帮助。谢谢你。

4

2 回答 2

1

我想详细说明 Juan Boero 的回答,虽然他说的是完全正确的,但我花了一些时间来找出解决方案,所以对于后来来这里寻找解决这个问题的具体方法的人来说,这就是我有:

当您使用capturedImage时,ARFrame您会收到一个CVPixelBuffer代表横向图像的图像(因为这就是 iPhone 的相机拍摄它的方式)。如果您尝试将此图像转换为正常方向,请使用

let transform = frame.displayTransform(
            for: screenOrientation,
            viewportSize: sceneView.bounds.size
).inverted()
let image = CIImage(cvPixelBuffer: frame.capturedImage).transformed(by: transform)

你会得到一个拉伸的图像,因为(至少在我的情况下)像素缓冲区的尺寸是1920x1440 (width x height)sceneView.bounds.size375x812 (height x width)。所以没有办法正常适应,1440x1920因为375x812它们不兼容。

如果您只需要图像,您实际上可以做的是将转换应用于像素缓冲区的倒置尺寸:

let width = CVPixelBufferGetWidth(frame.capturedImage)
let height = CVPixelBufferGetHeight(frame.capturedImage)
let transform = frame.displayTransform(
            for: screenOrientation,
            viewportSize: CGSize(width: height, height: width)
).inverted()
let image = CIImage(cvPixelBuffer: frame.capturedImage).transformed(by: transform)

这样,您将获得具有正确尺寸的正确旋转图像。

然后你可以用它做任何你想做的事情,例如裁剪以适应场景视图。

于 2020-04-29T10:08:03.857 回答
1

首先,我建议你复制一份ARFrame,否则currentFrame如果处理不及时,会出现各种奇怪的情况,因为内存会被硬件丢弃。

其次,拉伸是因为你使用的缓冲图像与视口图像不同,抓取一个session.snapshot并保存到你的mac,然后抓取你的cgImage并保存它,在预览中打开它们,你会看到大小不同,因此,当您想将较宽的图像放回视口大小时,它会拉伸。

你不需要一个演示项目,只需打印你的场景帧大小和缓冲区大小,检查两者之间的比率,你就会明白你的问题。

于 2020-04-21T23:40:46.120 回答