将cv::Mat转换为MTLTexture

4

我当前项目的一个中间步骤需要将opencv的cv::Mat转换为Metal的纹理容器MTLTexture。我需要将Mat中的Floats存储为纹理中的Floats,因为我的项目不能承受精度损失。

这是我尝试进行此类转换的方式。

- (id<MTLTexture>)texForMat:(cv::Mat)image context:(MBEContext *)context
{

  id<MTLTexture> texture;
  int width = image.cols;
  int height = image.rows;
  Float32 *rawData = (Float32 *)calloc(height * width * 4,sizeof(float));
  int bytesPerPixel = 4;
  int bytesPerRow = bytesPerPixel * width;
  float r, g, b,a;


  for(int i = 0; i < height; i++)
  {
    Float32* imageData = (Float32*)(image.data + image.step * i);
    for(int j = 0; j < width; j++)
    {
      r = (Float32)(imageData[4 * j]);
      g = (Float32)(imageData[4 * j + 1]);
      b = (Float32)(imageData[4 * j + 2]);
      a = (Float32)(imageData[4 * j + 3]);

      rawData[image.step * (i) + (4 * j)] = r;
      rawData[image.step * (i) + (4 * j + 1)] = g;
      rawData[image.step * (i) + (4 * j + 2)] = b;
      rawData[image.step * (i) + (4 * j + 3)] = a;
    }
  }


  MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA16Float
                                                                                               width:width
                                                                                              height:height
                                                                                           mipmapped:NO];
  texture = [context.device newTextureWithDescriptor:textureDescriptor];
  MTLRegion region = MTLRegionMake2D(0, 0, width, height);
  [texture replaceRegion:region mipmapLevel:0 withBytes:rawData bytesPerRow:bytesPerRow];

  free(rawData);
  return texture;
}

但是它似乎并没有起作用。每次从Mat中读取的都是零值,并且会抛出EXC_BAD_ACCESS异常。我需要在MTLPixelFormatRGBA16Float中使用MTLTexture以保持精度。
感谢您考虑这个问题。

我相信 image.step 是以字节为单位的。另外,我认为 OpenCV 通常使用 BGR 而不是 RGB,所以请检查您的通道顺序。而且,您似乎没有分配带有步幅 (必要的) image.steprawData,但是您正在使用它来访问它。 - chappjc
1个回答

3

这里的问题是你正在使用Float32加载rawData,但你的纹理是RGBA16Float,因此数据将会被破坏(16Float是Float32的一半大小)。这不应该导致崩溃,但这是一个你必须处理的问题。

另外,“chappjc”指出,当你写出你的数据时,你在使用'image.step',但该缓冲区应该是连续的,而且步长不应该超过(宽度*每像素字节数)。


当然,两个观点都是正确的,但由于我遇到了完全相同的问题,所以我只想确认 - 第二个观点是导致崩溃的原因。在迭代rawData时 - 例如rawData[image.step * (i) + (4 * j)] = r;应该改为rawData[bytesPerRow * i + (4 * j)] = r; - bartlomiej.n

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接