¿Cómo aplicar un Vignette CIFilter a un feed de cámara en vivo en iOS?
avfoundation core-image (1)
Al intentar aplicar un filtro de viñeta simple a la alimentación de cámara sin formato de un iPhone6, con la ayuda de Metal y Core Image, veo mucho retraso entre los marcos que se procesan y se procesan en un
MTKView
El enfoque que he seguido es (MetalViewController.swift):
-
Obtenga una salida de cámara sin procesar con
AVCaptureVideoDataOutputSampleBufferDelegate
-
Convertir
CMSampleBuffer
>CVPixelBuffer
>CGImage
-
Crea una
MTLTexture
con esteCGImage
.
Punto no.
2 y 3 están dentro del método llamado:
fillMTLTextureToStoreTheImageData
-
Aplique un
CIFilter
alCIImage
obtenido de laMTLTexture
en elMTKViewDelegate
func draw(in view: MTKView) {
if let currentDrawable = view.currentDrawable {
let commandBuffer = self.commandQueue.makeCommandBuffer()
if let myTexture = self.sourceTexture{
let inputImage = CIImage(mtlTexture: myTexture, options: nil)
self.vignetteEffect.setValue(inputImage, forKey: kCIInputImageKey)
self.coreImageContext.render(self.vignetteEffect.outputImage!, to: currentDrawable.texture, commandBuffer: commandBuffer, bounds: inputImage!.extent, colorSpace: self.colorSpace)
commandBuffer?.present(currentDrawable)
commandBuffer?.commit()
}
}
}
El rendimiento no es en absoluto lo que Apple mencionó en este documento: https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/CoreImaging/ci_tasks/ci_tasks.html#//apple_ref/doc/uid/TP30001185-CH3-TPXREF101
¿Me estoy perdiendo de algo?
El paso 2 es demasiado lento para admitir la representación en tiempo real ... y parece que te estás perdiendo un par de pasos. Para su propósito, usted típicamente:
Preparar:
-
crear un grupo de
CVPixelBuffer
- usandoCVPixelBufferPoolCreate
-
crear un conjunto de texturas metálicas utilizando
CVMetalTextureCacheCreate
Para cada cuadro:
-
convertir
CMSampleBuffer
>CVPixelBuffer
>CIImage
-
Pase ese
CIImage
través de su filtro de tubería -
renderizar la imagen de salida en un
CVPixelBuffer
desde el grupo creado en el paso 1 -
use
CVMetalTextureCacheCreateTextureFromImage
para crear una textura de metal con su CVPixelBuffer filtrado
Si se configura correctamente, todos estos pasos asegurarán que sus datos de imagen permanezcan en la GPU, en lugar de viajar de GPU a CPU y volver a GPU para su visualización.
La buena noticia es que todo esto se demuestra en el código de muestra de AVCamPhotoFilter de
https://developer.apple.com/library/archive/samplecode/AVCamPhotoFilter/Introduction/Intro.html#//apple_ref/doc/uid/TP40017556
.
En particular, vea la clase
RosyCIRenderer
y su superclase
FilterRenderer
.