如何裁剪/调整金属中的纹理阵列
答
我只想解决农作物的情况,因为调整大小的情况涉及到重采样,并且稍微复杂一些。让我知道你是否真的需要这个。
让我们假设您的源MPSImage
是128x128像素的12个特征通道(3切片)图像,您的目标图像是64x64像素的8个特征通道图像(2个切片),并且您要复制源的最后两个片的右下64x64区域放入目的地。
没有API,我所知道的,它允许你从/一次复制到一个数组质感的多个片,所以你需要发出多个blit的命令,以覆盖所有的切片:
let sourceRegion = MTLRegionMake3D(64, 64, 0, 64, 64, 1)
let destOrigin = MTLOrigin(x: 0, y: 0, z: 0)
let firstSlice = 1
let lastSlice = 2 // inclusive
let commandBuffer = commandQueue.makeCommandBuffer()
let blitEncoder = commandBuffer.makeBlitCommandEncoder()
for slice in firstSlice...lastSlice {
blitEncoder.copy(from: sourceImage.texture,
sourceSlice: slice,
sourceLevel: 0,
sourceOrigin: sourceRegion.origin,
sourceSize: sourceRegion.size,
to: destImage.texture,
destinationSlice: slice - firstSlice,
destinationLevel: 0,
destinationOrigin: destOrigin)
}
blitEncoder.endEncoding()
commandBuffer.commit()
答
我不确定为什么要剪裁,但请记住MPSCNN图层可以在MPSImage的较小部分上工作。只需设置offset
和clipRect
属性,该图层将只在源图像的该区域上工作。
事实上,你可以使用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()
我upvoted这两个问题的答案,但@ warrenm似乎更适合。我也喜欢你的想法。 – s1ddok
你还可以提供一个简单的代码,介绍如何用'NeuronLinear'裁剪'MPSImage'?我发现我需要将'a'设置为'1',将'b'设为'0',但不知道下一步该怎么做。 – s1ddok
如果'yourImage'是3通道图像(例如RGB),'tempImg'是1通道图像:如何使用linearNeuron实现通道更改? dest-region应该包含'R'或更好的灰色表示。当我用(,, 3)和(,, 1)指定ImageDescriptors时,整个事件都会崩溃。 – Chris