当应用程序不再需要时,如何从 运行 停止 CoreML?

How to stop CoreML from running when it's no longer needed in the app?

我的应用程序在 CoreML 模型上运行 Vision。运行机器学习模型的相机帧来自 ARKit sceneView(基本上是相机)。我有一个名为 loopCoreMLUpdate() 的方法,它会持续运行 CoreML,以便我们在新相机帧上保持 运行 模型。代码如下所示:

import UIKit
import SceneKit
import ARKit

class MyViewController: UIViewController {
    var visionRequests = [VNRequest]()
    let dispatchQueueML = DispatchQueue(label: "com.hw.dispatchqueueml") // A Serial Queue

    override func viewDidLoad() {
        super.viewDidLoad()

        // Setup ARKit sceneview
        // ...

        // Begin Loop to Update CoreML
        loopCoreMLUpdate()
    }

    // This is the problematic part. 
    // In fact - once it's run there's no way to stop it, is there?
    func loopCoreMLUpdate() {
        // Continuously run CoreML whenever it's ready. (Preventing 'hiccups' in Frame Rate)

        dispatchQueueML.async {
            // 1. Run Update.
            self.updateCoreML()

            // 2. Loop this function.
            self.loopCoreMLUpdate()
        }   
    }

    func updateCoreML() {
        ///////////////////////////
        // Get Camera Image as RGB
        let pixbuff : CVPixelBuffer? = (sceneView.session.currentFrame?.capturedImage)
        if pixbuff == nil { return }
        let ciImage = CIImage(cvPixelBuffer: pixbuff!)
        // Note: Not entirely sure if the ciImage is being interpreted as RGB, but for now it works with the Inception model.
        // Note2: Also uncertain if the pixelBuffer should be rotated before handing off to Vision (VNImageRequestHandler) - regardless, for now, it still works well with the Inception model.

        ///////////////////////////
        // Prepare CoreML/Vision Request
        let imageRequestHandler = VNImageRequestHandler(ciImage: ciImage, options: [:])
        // let imageRequestHandler = VNImageRequestHandler(cgImage: cgImage!, orientation: myOrientation, options: [:]) // Alternatively; we can convert the above to an RGB CGImage and use that. Also UIInterfaceOrientation can inform orientation values.

        ///////////////////////////
        // Run Image Request
        do {
            try imageRequestHandler.perform(self.visionRequests)
        } catch {
            print(error)
        }

    }

}

如您所见,循环效果是由 DispatchQueue 和标签 com.hw.dispatchqueueml 不断调用 loopCoreMLUpdate() 创建的。一旦不再需要 CoreML,有没有办法停止队列?完整代码是 here.

我建议在 viewDidLoad 中使用 运行 coreML 模型,您可以使用 ARSessionDelegate 函数。 func session(_ session: ARSession, didUpdate frame: ARFrame) 方法来获取帧,你可以设置标志,在这里当你想让模型工作和不工作时启用。 像下面这样:

func session(_ session: ARSession, didUpdate frame: ARFrame) { // 这是我们分析框架的地方

      // We return early if currentBuffer is not nil or the tracking state of camera is not normal

    // TODO: - Core ML Functionality Commented
      guard isMLFlow else { //
             return
      }
      currentBuffer = frame.capturedImage
      guard let buffer = currentBuffer, let image = UIImage(pixelBuffer: buffer) else { return }
     <Code here to load model>
      CoreMLManager.manager.updateClassifications(for: image)
}