我正在构建一个 iOS 应用程序,可以将相机中的帧实时渲染到金属纹理。我想使用 CoreML 在金属纹理的子区域上执行样式转移(将相机输出想象为 2x2 网格,其中 4 个正方形中的每一个都用作样式转移网络的输入,并将输出粘贴回显示的纹理中) )。我试图找出如何最好地在 Metal 管道内使用 CoreML,用 mlmodel 的输出填充纹理的非重叠子区域(希望不要将 mlmodel 分解为 MPSNNGraph)。是否可以直接将 MTLTexture 或 MTLBuffer 提供给 coreML 模型?我想尽可能避免格式转换(为了速度)。
我的 mlmodel 在其输入和输出处采用 CVPixelBuffers。可以用 MTLTextures 来代替吗?
我尝试的第一件事是:将给定的样本缓冲区切割成子区域(通过复制像素数据呃),推断每个子区域,然后将它们粘贴到一个新的样本缓冲区中,然后将其转换为 MTLTexture 并显示。这种方法根本没有利用金属,因为纹理是在推理之后才创建的。它还存在大量迂回的转换/复制/粘贴操作,这会减慢一切速度。
我尝试的第二件事是:将相机数据直接发送到 MTLTexture,推断样本缓冲区的子区域,针对每个子区域使用 MTLTexture.replace(region:...withBytes:) 粘贴到当前显示的纹理中。然而,MTLTexture.replace() 使用 CPU,对于实时视频来说速度不够快。
我要尝试的想法是:将我的 mlmodel 转换为 MPSNNGraph,获取帧作为纹理,使用 MPSNNGraph 对子区域进行推理,并显示输出。我想我应该先检查一下这里,然后再完成转换 mlmodel 的所有工作。抱歉,如果这太宽泛了,我主要从事张量流工作,这里有点超出我的深度。
免责声明:我不使用 CoreML 或 Metal,所以这只是一个概念。
如果 CoreML 不允许使用
MTLTexture
,但允许使用 CVPixelBuffer
,那么您可以尝试创建共享 GPU/CPU 内存,这样当您获得 MTLTexture
时,您也可以访问 CVPixelBuffer
。
例如,您可以为此目的研究:CVMetalTextureCacheCreateTextureFromImage。
请注意共享 GPU/CPU 内存可能需要额外的同步措施。