我当前项目的一个中间步骤需要将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.step
的rawData
,但是您正在使用它来访问它。 - chappjc