如何有效地从CMSampleBuffer数据生成的CIImage中读取像素值?

时间:2017-09-19 03:27:01

标签: ios avcapturesession core-image

我正在从iOS AVCaptureSesion读取样本缓冲区,对它们执行一些简单的图像处理,然后从结果图像中分析像素。我使用openCV进行图像处理,但是我想切换到核心图像,我希望这些操作能更有效。但是我完全坚持如何从生成的CIImage中读取像素值。

当我有一个由CGImage支持的UIImage时,我可以使用cgImage dataProvider来访问底层像素数据(例如下面的例子)。但是CIImage的模拟是什么?

以下是我的总体流程:

    // 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]
      }     
  }

我已经尝试使用CIContext来获得一个CGImage支持的UIImage,如下所示,但事实证明这种效率非常低 - 每帧占用一小部分时间(比等效的openCV操作长几百倍)。

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

我还应该提到我的滤镜图像很小(我正在缩小它)。我不知道这是否会引起一些问题。

我错过了什么?感谢。

更新:经过一些实验,结果证明CI中的缩放选项比OpenCV中的缩放选项慢很多。在我的项目中仅仅为了缩放而包含OpenCV感觉是错误的,但是......目前。

1 个答案:

答案 0 :(得分:1)

  

但是我完全不知道如何从生成的CIImage中读取像素值

这个概念毫无意义。 CIImage没有像素值。它只是一组制作图像的说明。那是Core Image的;在渲染时间之前没有任何事当你说context.createCGImage(filteredImage, from: ciImage.extent)时, 渲染时间 - 这是一项耗时,计算密集的操作。