ARFrame.capturedImage CVPixelBufferRef 到 OpenCv Mat 的实时转换

Realtime conversion of ARFrame.capturedImage CVPixelBufferRef to OpenCv Mat

ARKit 以 60 frames/sec 运行,相当于每帧 16.6 毫秒。

我当前将 CVPixelBufferRef(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange 格式)转换为 cv::Mat (YCrCb) 的代码在 30 毫秒内运行,这导致 ARKit 停滞并且一切都滞后。

有没有人知道如何更快地转换或者我是否需要降低帧速率?

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

我也可以只使用灰度平面,这是第一个通道,运行时间 <1ms,但理想情况下我还需要颜色信息。

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

  1. 调用 CVMetalTextureCacheCreateTextureFromImage 在像素缓冲区顶部创建 CVMetalTexture 对象。
  2. 调用CVMetalTextureGetTexture创建一个MTLTexture对象,Metal代码(GPU)可以读写。
  3. 写一些Metal代码来转换颜色格式。

我有一个开源项目 (https://github.com/snakajima/vs-metal),它使用 Metal 处理像素缓冲区(来自相机,而不是 ARKit)。随意复制此项目中的任何代码。

我尝试将 Ycbcr 转换为 RGB,在 RGB mat 中进行图像处理并将其转换回 Ycbcr,它工作得非常慢。我建议只用静态图像来做。对于实时处理,我们应该直接在cv::Mat中处理。 ARFrame.capturedImage 是 Ycbcr 缓冲区。所以,解决方案是

  1. 将缓冲区拆分为 2 cv::Mat(yPlane 和 cbcrPlane)。请记住,我们不克隆内存,我们创建 2 cv::Mat,基地址是 yPlane 地址和 cbcrPlane 地址。
  2. 在yPlane和cbcrPlane上做图像处理,size(cbcrPlane) = size(yPlane) / 2.

你可以在这里查看我的代码:https://gist.github.com/ttruongatl/bb6c69659c48bac67826be7368560216