Search code examples
iosswiftfiltermetal

How to apply MPSImageGuidedFilter in Swift


I applied OpenCV guided filter for my project in Python successfully and now I have to carry this function to my iOS application. I searched Apple developer website and found out a filter called MPSImageGuidedFilter. I suppose it works in a similar way as OpenCV guided filter. However, my limited knowledge of iOS programming does not let me figure out how to use it. Unfortunately, I could not find a sample code on the web too. Is there anyone who used this filter before? I really appreciate the help. Or a sample code using any filter under MPS would be helpful to figure out.


Solution

  • After a few days of hard work, I managed to make MPSImageGUidedFilter. Please see below the code who wants to work on:

    import UIKit
    import MetalPerformanceShaders
    import MetalKit
    
    class ViewController: UIViewController {
        
        public var texIn: MTLTexture!
        
        public var coefficient: MTLTexture!
    
        public var context: CIContext!
        
        let device = MTLCreateSystemDefaultDevice()!
        var queue: MTLCommandQueue!
        var Metalview: MTKView { return view as! MTKView }
    
        override func viewDidLoad() {     
            super.viewDidLoad()
            
            Metalview.drawableSize.height = 412
            Metalview.drawableSize.width = 326
            Metalview.framebufferOnly = false
            Metalview.device = device
           
            Metalview.delegate = self
            
            queue = device.makeCommandQueue()
            let textureLoader = MTKTextureLoader(device: device)
            
            let urlCoeff = Bundle.main.url(forResource: "mask", withExtension: "png")
            do {
                coefficient = try textureLoader.newTexture(URL: urlCoeff!, options: [:])
            } catch {
                fatalError("coefficient file not uploaded")
            }
            
            let url = Bundle.main.url(forResource: "guide", withExtension: "png")
            do {
                texIn = try textureLoader.newTexture(URL: url!, options: [:])
            } catch {
                fatalError("resource file not uploaded")
            }
        }
        
    }
    
    extension ViewController: MTKViewDelegate {
    
        func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {}
    
        func draw(in view: MTKView) {
            guard let commandBuffer = queue.makeCommandBuffer(),
                  let drawable = view.currentDrawable else {
                return
            }
          
            let shader = MPSImageGuidedFilter(device: device, kernelDiameter: 5)
            shader.epsilon = 0.001
    
            let textOut = drawable.texture
            
            shader.encodeReconstruction(to: commandBuffer, guidanceTexture: texIn, coefficientsTexture: coefficient, destinationTexture: textOut)
    
            commandBuffer.present(drawable)
            commandBuffer.commit()
        }
    
    }