ios avfoundation core-image cifilter metalkit

¿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):

  1. Obtenga una salida de cámara sin procesar con AVCaptureVideoDataOutputSampleBufferDelegate
  2. Convertir CMSampleBuffer > CVPixelBuffer > CGImage
  3. Crea una MTLTexture con este CGImage .

Punto no. 2 y 3 están dentro del método llamado: fillMTLTextureToStoreTheImageData

  1. Aplique un CIFilter al CIImage obtenido de la MTLTexture en el MTKViewDelegate

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:

  1. crear un grupo de CVPixelBuffer - usando CVPixelBufferPoolCreate
  2. crear un conjunto de texturas metálicas utilizando CVMetalTextureCacheCreate

Para cada cuadro:

  1. convertir CMSampleBuffer > CVPixelBuffer > CIImage
  2. Pase ese CIImage través de su filtro de tubería
  3. renderizar la imagen de salida en un CVPixelBuffer desde el grupo creado en el paso 1
  4. 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 .