簡體   English   中英

使用 CIFilter 進行渲染時,實時攝像機被拉伸。 - Swift 4

[英]Live camera is getting stretched while rendering using CIFilter. - Swift 4

我想在渲染時應用相機濾鏡,我的代碼是......

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)
        }
}

在運行時,output 會被拉伸。 我附上了兩張圖片,

  1. 普通相機渲染
  2. 帶濾鏡相機渲染。

這是正常的相機渲染,看起來不錯,

這是帶濾鏡的實時攝像機,您可以在運行時看到實時攝像機被拉伸。

請幫我解決它,如果您提供任何演示代碼或項目將有很大幫助。 謝謝你。

首先,我建議你制作一個ARFrame的副本,否則如果沒有及時處理currentFrame會變得很奇怪,因為 memory 將被硬件丟棄。

其次,拉伸是因為你使用的緩沖圖像與視口圖像不同,抓取一個session.snapshot並保存到你的 mac,然后抓取你的cgImage並保存它,在預覽中打開它們,你會看到尺寸不同,因此,當您要將較寬的圖像放回視口尺寸時,它會拉伸。

你不需要一個演示項目,只需打印你的場景幀大小和緩沖區大小,檢查兩者之間的比率,你就會明白你的問題。

我想詳細說明 Juan Boero 的回答,雖然他說的是完全正確的,但我花了一些時間來找出解決方案,所以對於后來來這里尋找解決這個問題的具體方法的人來說,這就是我有:

當您使用capturedImageARFrame時,您會收到一個代表橫向圖像的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)

這樣,您將獲得具有正確尺寸的正確旋轉圖像。

然后你可以用它做任何你想做的事情,例如裁剪以適應場景視圖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM