gpt4 book ai didi

ios - 在 iPhone 的 GPU( Metal )和 CPU(OpenCV)上处理摄像头馈送数据

转载 作者:IT王子 更新时间:2023-10-29 08:20:49 26 4
gpt4 key购买 nike

我在 iOS 上以 120 fps 的速度进行实时视频处理,我想先在 GPU 上预处理图像(在 CPU 上速度不够快的下采样、转换颜色等),然后使用 OpenCV 在 CPU 上对帧进行后处理。

使用 Metal 在 GPU 和 CPU 之间共享摄像头信号的最快方法是什么?

换句话说,管道看起来像:

CMSampleBufferRef -> MTLTexture or MTLBuffer -> OpenCV Mat

我正在按以下方式转换 CMSampleBufferRef -> MTLTexture

CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

// textureRGBA
{
size_t width = CVPixelBufferGetWidth(pixelBuffer);
size_t height = CVPixelBufferGetHeight(pixelBuffer);
MTLPixelFormat pixelFormat = MTLPixelFormatBGRA8Unorm;

CVMetalTextureRef texture = NULL;
CVReturn status = CVMetalTextureCacheCreateTextureFromImage(NULL, _textureCache, pixelBuffer, NULL, pixelFormat, width, height, 0, &texture);
if(status == kCVReturnSuccess) {
textureBGRA = CVMetalTextureGetTexture(texture);
CFRelease(texture);
}
}

在我的 Metal 着色器完成后,我将 MTLTexture 转换为 OpenCV

cv::Mat image;
...
CGSize imageSize = CGSizeMake(drawable.texture.width, drawable.texture.height);
int imageByteCount = int(imageSize.width * imageSize.height * 4);
int mbytesPerRow = 4 * int(imageSize.width);

MTLRegion region = MTLRegionMake2D(0, 0, int(imageSize.width), int(imageSize.height));
CGSize resSize = CGSizeMake(drawable.texture.width, drawable.texture.height);
[drawable.texture getBytes:image.data bytesPerRow:mbytesPerRow fromRegion:region mipmapLevel:0];

一些观察:

1) 不幸的是 MTLTexture.getBytes 看起来很昂贵(将数据从 GPU 复制到 CPU?)并且在我的 iphone 5S 上需要大约 5ms,这在以 ~100fps 处理时太多了

2) 我注意到有些人通过以下方法使用 MTLBuffer 而不是 MTLTexture: metalDevice.newBufferWithLength(byteCount,选项:.StorageModeShared)(参见:Memory write performance - GPU CPU Shared Memory)

不过,猜测 CMSampleBufferRef 和随附的 CVPixelBufferRef 是由 CoreVideo 管理的。

最佳答案

最快的方法是使用由 MTLBuffer 支持的 MTLTexture;它是一种特殊的 MTLTexture,与 MTLBuffer 共享内存。但是,您的 C 处理 (openCV) 将落后一两帧,这是不可避免的,因为您需要将命令提交给 GPU(编码)并且 GPU 需要渲染它,如果您使用 waitUntilCompleted 来确保 GPU完了只会吃掉 CPU 很浪费。

所以过程是:首先创建 MTLBuffer,然后使用 MTLBuffer 方法“newTextureWithDescriptor:offset:bytesPerRow:”创建特殊的 MTLTexture。您需要事先创建特殊的 MTLTexture(作为实例变量),然后您需要设置一个标准渲染管道(比使用计算着色器更快),它将采用从 CMSampleBufferRef 创建的 MTLTexture 并将其传递到您的特殊 MTLTexture,在一次通过,您可以缩小比例并根据需要进行任何颜色转换。然后你将命令缓冲区提交给 gpu,在随后的传递中你可以调用 [theMTLbuffer contents] 来获取指向支持你的特殊 MTLTexture 的字节的指针,以便在 openCV 中使用。

任何强制停止 CPU/GPU 行为的技术永远不会有效,因为一半的时间将花费在等待上,即 CPU 等待 GPU 完成,GPU 也必须等待下一个编码(当GPU 正在工作您希望 CPU 编码下一帧并执行任何 openCV 工作而不是等待 GPU 完成)。

此外,当人们通常提到实时处理时,他们通常指的是一些具有实时反馈(视觉)的处理,所有 4s 及更高版本的现代 iOS 设备都有 60Hz 的屏幕刷新率,因此任何反馈都呈现比这更快是没有意义的,但如果你需要 2 帧(120Hz)来制作 1(60Hz),那么你必须有一个自定义计时器或修改 CADisplayLink。

关于ios - 在 iPhone 的 GPU( Metal )和 CPU(OpenCV)上处理摄像头馈送数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37639271/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com