2017-09-19 7 views
2

Je suis en train de lire des tampons d'échantillons d'une AVCaptureSesion iOS, d'effectuer une manipulation d'image simple sur eux, puis d'analyser les pixels des images résultantes. Je l'ai fait en utilisant openCV pour le traitement d'image, mais je voudrais passer à l'image de base, qui, je l'espère, sera plus efficace pour ces opérations simples. Cependant, je suis complètement bloqué sur la façon de lire les valeurs de pixels à partir du CIImage résultant.Comment puis-je lire efficacement les valeurs de pixels d'un CIImage généré à partir de données CMSampleBuffer?

Lorsque j'ai un UIImage soutenu par une CGImage, je peux utiliser le dataProvider cgImage pour accéder aux données de pixel sous-jacentes (exemple ci-dessous). Mais quel est l'analogue avec CIImage?

Voici mon flux général:

// Getting sample video data 
    var session : AVCaptureSession = AVCaptureSession() 

    // processing the sample buffer with core image 
    func handleSampleBuffer(sampleBuffer: CMSampleBuffer) 
    {  
     let cvImage: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)! 
     let ciImage: CIImage = CIImage(cvPixelBuffer: cvImage) 

     let filteredImage = processWithCoreImage(image: ciImage) 

     // 
    // How can I efficiently get pixel values from filtered image here? 
     // 
    } 

    func processWithCoreImage(image: CIImage) -> CIImage 
    { 
     // process with a core image filter chain 
     let filter1 = CIFilter(name: “…”)! 
     filter1.setValue(image, forKey: kCIInputImageKey) 
     filter1.setValue(…, forKey: …) 
     … 
     let outputImage = filter.outputImage 
     return outputImage 
    } 

    // With a regular UIImage I was doing something like this to get pixel data 
    // However CIImage does not have a cgImage backing it in this case. 
    public extension UIImage { 
     func getPixelValueGrayscale(x: Int, y: Int) -> UInt8 { 
      let pixelData = self.cgImage!.dataProvider!.data 
      let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData) 
      let pixelInfo: Int = ((Int(self.size.width) * Int(y)) + Int(x)) 
      return data[pixelInfo] 
     }  
    } 

J'ai essayé d'utiliser CIContext pour obtenir un CGImage soutenu UIImage comme suit, mais cela est avéré terriblement inefficace - était de prendre une bonne fraction de seconde pour chaque trame (centaines de temps plus longs que les opérations openCV équivalentes).

// re-used CIContext 
let cgImage = context.createCGImage(filteredImage, from: ciImage.extent) 
let img = UIImage(cgImage: cgImage!) 

Je devrais aussi mentionner que mon image filtrée est minuscule (je la redimensionne). Je ne sais pas si cela cause un problème.

Qu'est-ce qui me manque? Merci. MISE À JOUR: Après quelques expériences, il s'est avéré que les options de mise à l'échelle dans CI sont beaucoup plus lentes que celles disponibles dans OpenCV. C'est une erreur d'inclure OpenCV dans mon projet juste pour la mise à l'échelle, mais ... pour le moment.

+0

J'ai voté la "réponse" de @matt même si elle n'a pas vraiment répondu (désolé). Il semble que vous souhaitiez travailler avec l'appareil photo en "temps réel". (Il avait raison, ce n'est pas un moyen efficace.) Je ne suis pas un expert, mais voici un lien vers quelqu'un qui est: http://flexmonkey.blogspot.com/2015/12/cartooneyes-compositing-cartoon- eyes.html? view = magazine. Si ce lien ne fonctionne pas? Regardez le reste de ses articles de blog. * Techniquement *, vous * ne * voulez utiliser CI, juste * pas * la façon dont vous avez posté. (Désolé pour l'utilisation de l'italique - en essayant de souligner.) – dfd

+0

Merci d'avoir signalé ce problème. Je me demandais juste comment cela s'était passé. N'hésitez pas à répondre à votre propre question, et même (dans quelques jours) à accepter votre propre réponse. – matt

Répondre

1

Cependant, je suis complètement coincé sur la façon de lire les valeurs de pixel du résultat CIImage

La notion n'a pas de sens. Un CIImage n'a pas de valeurs de pixels. C'est juste un ensemble d'instructions pour faire une image. C'est le point de Core Image; rien n'arrive avant de rendre le temps. Quand vous dites context.createCGImage(filteredImage, from: ciImage.extent), que est temps de rendu - et c'est une opération de temps, de calcul intensif.

+0

Donc, peut-être que je ne me trompe pas, mais la question demeure: comment puis-je obtenir efficacement les données de pixel rendues par la chaîne de filtres? Si l'appel ci-dessus est correct, je dois faire autre chose de mal parce que c'est incroyablement lent. Je vais essayer de poster un projet d'exemple de travail demain. –