Wie wende ich einen Vignette CIFilter auf einen Live-Kamera-Feed in iOS an?



avfoundation core-image (1)

Beim Versuch, mit Hilfe von Metal und Core Image einen einfachen Vignettenfilter auf den Rohkamera-Feed eines iPhone6 ​​anzuwenden, treten große Verzögerungen zwischen den Bildern auf, die in einem MTKView verarbeitet und gerendert MTKView

Der Ansatz, dem ich gefolgt bin, ist (MetalViewController.swift):

  1. Mit AVCaptureVideoDataOutputSampleBufferDelegate
  2. Konvertieren Sie CMSampleBuffer > CVPixelBuffer > CGImage
  3. Erstellen MTLTexture mit diesem CGImage eine CGImage .

Punkt Nr. 2 und 3 befinden sich in der Methode fillMTLTextureToStoreTheImageData

  1. Wenden Sie einen CIFilter auf das CIFilter an, das aus der MTLTexture im 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()
            }
        }
    }

Die Leistung entspricht in keiner Weise den Angaben von Apple in diesem Dokument: https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/CoreImaging/ci_tasks/ci_tasks.html#//apple_ref/doc/uid/TP30001185-CH3-TPXREF101

Vermisse ich etwas?


Ihr Schritt 2 ist viel zu langsam, um Echtzeit-Rendering zu unterstützen ... und es sieht so aus, als würden Ihnen einige Schritte fehlen. Für Ihren Zweck würden Sie normalerweise:

Konfiguration:

  1. Erstellen Sie einen Pool von CVPixelBuffer - mit CVPixelBufferPoolCreate
  2. Erstellen Sie mit CVMetalTextureCacheCreate einen Pool von Metalltexturen

Für jeden Rahmen:

  1. konvertiere CMSampleBuffer > CVPixelBuffer > CIImage
  2. CIImage Sie das CIImage durch Ihre CIImage
  3. Rendern Sie das Ausgabebild in einen CVPixelBuffer aus dem in Schritt 1 erstellten Pool
  4. Verwenden Sie CVMetalTextureCacheCreateTextureFromImage , um mit Ihrem gefilterten CVPixelBuffer eine Metalltextur zu erstellen

Bei korrekter Einrichtung stellen alle diese Schritte sicher, dass Ihre Bilddaten auf der GPU verbleiben, anstatt von der GPU zur CPU und zurück zur GPU zur Anzeige zu gelangen.

Die gute Nachricht ist, dass all dies im AVCamPhotoFilter-Beispielcode von Apple unter https://developer.apple.com/library/archive/samplecode/AVCamPhotoFilter/Introduction/Intro.html#//apple_ref/doc/uid/TP40017556 demonstriert wird. Siehe insbesondere die RosyCIRenderer Klasse und ihren FilterRenderer Superklasse.