Comment appliquer un Vignette CIFilter à un flux de caméra en direct sous iOS?



avfoundation core-image (1)

Votre étape 2 est bien trop lente pour prendre en charge le rendu en temps réel ... et il semble qu'il vous manque quelques étapes. Pour ce faire, vous devez généralement:

Installer:

  1. créer un pool de CVPixelBuffer - en utilisant CVPixelBufferPoolCreate
  2. créer un pool de textures métalliques à l'aide de CVMetalTextureCacheCreate

Pour chaque image:

  1. convertir CMSampleBuffer > CVPixelBuffer > CIImage
  2. Passez ce CIImage travers votre pipeline de filtres
  3. restituer l'image de sortie dans un CVPixelBuffer partir du pool créé à l'étape 1
  4. Utilisez CVMetalTextureCacheCreateTextureFromImage pour créer une texture en métal avec votre CVPixelBuffer filtré.

Si elles sont correctement configurées, toutes ces étapes garantiront que vos données d'image restent sur le processeur graphique, par opposition à un déplacement d'un processeur graphique à un processeur et à un retour sur le processeur graphique pour l'affichage.

La bonne nouvelle est que tout ceci est présenté dans l'exemple de code AVCamPhotoFilter d'Apple https://developer.apple.com/library/archive/samplecode/AVCamPhotoFilter/Introduction/Intro.html#//apple_ref/doc/uid/TP40017556 . Voir en particulier la classe RosyCIRenderer et sa super-classe FilterRenderer .

En essayant d'appliquer un filtre de vignette simple au flux de caméra brut d'un iPhone6, avec l'aide de Metal et Core Image, je constate un décalage important entre les images en cours de traitement et de rendu dans un MTKView

L’approche que j’ai suivie est (MetalViewController.swift):

  1. Obtenez une sortie de caméra brute en utilisant AVCaptureVideoDataOutputSampleBufferDelegate
  2. Convertir CMSampleBuffer > CVPixelBuffer > CGImage
  3. Créez une MTLTexture avec cette image CGImage .

Point no 2 et 3 se trouvent dans la méthode nommée: fillMTLTextureToStoreTheImageData

  1. Appliquer un CIFilter au CIImage extrait de MTLTexture dans 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()
            }
        }
    }

La performance n’est pas du tout ce que Apple a mentionné dans cette documentation: https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/CoreImaging/ci_tasks/ci_tasks.html#//apple_ref/doc/uid/TP30001185-CH3-TPXREF101

Est-ce que je manque quelque chose?