如何在Metal中裁剪/调整纹理数组的大小

时间:2017-02-28 12:59:46

标签: metal

假设我有一个基于MPSImage的N通道MTLTexture或纹理数组。

如何从中裁剪区域,复制所有N个频道,但更改"像素大小"?

2 个答案:

答案 0 :(得分:4)

我只是解决了裁剪案例,因为调整大小的情况涉及重新取样并且稍微复杂一些。如果你确实需要,请告诉我。

假设你的源default是12个特征通道(3切片)图像,其为1​​28x128像素,目标图像是8个特征通道图像(2个切片),即64x64像素,并且您要将源的最后两个切片的右下角64x64区域复制到目标。

我所知道的API不允许您同时从/向数组纹理的多个切片复制,因此您需要发出多个blit命令来覆盖所有切片:

options: {
  legend: {
    position: 'top',
    labels: {
      fontColor: 'rgb(255, 99, 132)'
    },
    onHover: function(event, legendItem) {
      document.getElementById("canvas").style.cursor = 'pointer';
    }
  },
  tooltips: {
    custom: function(tooltip) {
      if (!tooltip.opacity) {
        document.getElementById("canvas").style.cursor = 'default';
        return;
      }
    }
  }
}

答案 1 :(得分:3)

我不确定你想要裁剪的原因,但请记住,MPSCNN图层可以在MPSImage的较小部分上工作。只需设置offsetclipRect属性,该图层仅适用于源图像的该区域。

事实上,您可以使用MPSCNNNeuronLinear以这种方式完成作物。不确定它是否比使用blit编码器更快或更慢,但它肯定更简单。

编辑添加了一个代码示例。这是从内存中输入的,所以它可能有很小的错误,但这是一般的想法:

// Declare this somewhere:
let linearNeuron = MPSCNNNeuronLinear(a: 1, b: 0)

然后当您运行神经网络时,添加以下内容:

let yourImage: MPSImage = ...
let commandBuffer = ...

// This describes the size of the cropped image.
let imgDesc = MPSImageDescriptor(...)

// If you're going to use the cropped image in other layers 
// then it's a good idea to make it a temporary image.
let tempImg = MPSTemporaryImage(commandBuffer: commandBuffer, imageDescriptor: imgDesc)

// Set the cropping offset:
linearNeuron.offset = MPSOffset(x: ..., y: ..., z: 0)

// The clip rect is the size of the output image.
linearNeuron.clipRect = MTLRegionMake(0, 0, imgDesc.width, imgDesc.height)

linearNeuron.encode(commandBuffer: commandBuffer, sourceImage: yourImage, destinationImage: tempImg)

// Here do your other layers, taking tempImg as input.
. . .

commandBuffer.commit()