10

我正在尝试在 Apple 的原生相机中模仿肖像模式。

问题是,对深度数据应用模糊效果CIImage对于我想向用户显示的实时预览来说太慢了。

我的代码是任务是:

func blur(image: CIImage, mask: CIImage, orientation: UIImageOrientation = .up, blurRadius: CGFloat) -> UIImage? {
    let start = Date()
    let invertedMask = mask.applyingFilter("CIColorInvert")
    
    let output = image.applyingFilter("CIMaskedVariableBlur", withInputParameters: ["inputMask" : invertedMask,
                                                                                    "inputRadius": blurRadius])
    
    guard let cgImage = context.createCGImage(output, from: image.extent) else {
        return nil
    }
    let end = Date()
    let elapsed = end.timeIntervalSince1970 - start.timeIntervalSince1970
    print("took \(elapsed) seconds to apply blur")
    return UIImage(cgImage: cgImage, scale: 1.0, orientation: orientation)
}

我想在 GPU 上应用模糊以获得更好的性能。对于这个任务,我在这里找到了 Apple 提供的这个实现。

所以在 Apple 的实现中,我们有这个代码片段:

/** Applies a Gaussian blur with a sigma value of 0.5.
 This is a pre-packaged convolution filter.
 */
class GaussianBlur: CommandBufferEncodable {
    let gaussian: MPSImageGaussianBlur

    required init(device: MTLDevice) {
        gaussian = MPSImageGaussianBlur(device: device,
                                    sigma: 5.0)
    }

    func encode(to commandBuffer: MTLCommandBuffer, sourceTexture: MTLTexture, destinationTexture: MTLTexture) {
        gaussian.encode(commandBuffer: commandBuffer,
                    sourceTexture: sourceTexture,
                    destinationTexture: destinationTexture)
    }
}

如何通过 Metal blur 版本将深度数据应用到过滤中?或者换句话说 - 我怎样才能以第二个代码片段的性能速度实现第一个代码片段功能?

4

1 回答 1

0

对于仍在寻找的人,您需要先入为主currentDrawabledraw(in view: MTKView)实施MTKViewDelegate

func makeBlur() {
    device = MTLCreateSystemDefaultDevice()
    commandQueue = device.makeCommandQueue()
    
    selfView.mtkView.device = device
    selfView.mtkView.framebufferOnly = false
    selfView.mtkView.delegate = self
    
    let textureLoader = MTKTextureLoader(device: device)
    if let image = self.backgroundSnapshotImage?.cgImage, let texture = try? textureLoader.newTexture(cgImage: image, options: nil) {
        sourceTexture = texture
    }
}

func draw(in view: MTKView) {
    if let currentDrawable = view.currentDrawable,
       let commandBuffer = commandQueue.makeCommandBuffer() {
           let gaussian = MPSImageGaussianBlur(device: device, sigma: 5)
           gaussian.encode(commandBuffer: commandBuffer, sourceTexture: sourceTexture, destinationTexture: currentDrawable.texture)
           commandBuffer.present(currentDrawable)
           commandBuffer.commit()
    }
}
于 2022-02-28T18:06:01.870 回答