将ARFrame.capturedImage CVPixelBufferRef实时转换为OpenCv Mat

时间:2017-07-05 11:24:21

标签: ios opencv arkit

ARKit以60帧/秒的速度运行,相当于每帧16.6毫秒。

我目前将CVPixelBufferRef(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange格式)转换为cv :: Mat(YCrCb)的代码在30ms内运行,这会导致ARKit停滞并且所有内容都会滞后。

有没有人对如何更快地转换有任何想法,还是我需要降低帧速率?

有一个suggestion by Apple to use Metal,但我不知道该怎么做。

此外,我可以采用灰度平面,这是第一个以<1ms运行的通道,但理想情况下我也需要颜色信息。

2 个答案:

答案 0 :(得分:3)

要使用Metal处理像素缓冲区中的图像,您需要执行以下操作。

  1. 调用CVMetalTextureCacheCreateTextureFromImage以在像素缓冲区顶部创建CVMetalTexture对象。
  2. 调用CVMetalTextureGetTexture创建一个MTLTexture对象,Metal Code(GPU)可以读取和写入。
  3. 写一些金属代码来转换颜色格式。
  4. 我有一个开源项目(https://github.com/snakajima/vs-metal),它使用Metal处理像素缓冲区(来自相机,而不是ARKit)。随意复制此项目中的任何代码。

答案 1 :(得分:1)

我试图将Ycbcr转换为RGB,在RGB垫中进行图像处理,然后将其转换回Ycbcr,它工作非常缓慢。我建议只使用静态图像。对于实时处理,我们应该直接在cv :: Mat中进行处理。 ARFrame.capturedImage是Ycbcr缓冲区。因此,解决方案是

  1. 将缓冲区分配到2 cv :: Mat(yPlane和cbcrPlane)。请记住,我们不克隆内存,我们创建2个cv :: Mat,其基地址为yPlane地址和cbcrPlane地址。
  2. 在yPlane和cbcrPlane上执行图像处理,大小(cbcrPlane)=大小(yPlane)/ 2。

您可以在此处查看我的代码:https://gist.github.com/ttruongatl/bb6c69659c48bac67826be7368560216