19-苹果官方ARKit+Vision+Core ML联合使用Demo解读

说明

ARKit文章目录

本文是对WWDC2018后推出的UsingVisionInRealTimeWithARKitDemo的解读.苹果在这个demo中演示了如何在ARKit中联合使用Vision和Core ML,并提出了一些注意事项.


主要内容

本Demo的主要内容是,从ARKit中获取视频帧,利用Vision中的ML请求,图像传给mlmodel模型,处理后得到的结果也是经过Vision框架返回,再在AR场景中放置SKNode节点展示出来.

最核心的代码只有两三个方法:

    // MARK: - ARSessionDelegate

    // Pass camera frames received from ARKit to Vision (when not already processing one)
    // 将从ARKit中得到的相机视频帧传到Vision(当没有正在处理的帧时)
    /// - Tag: ConsumeARFrames
    func session(_ session: ARSession, didUpdate frame: ARFrame) {
        // Do not enqueue other buffers for processing while another Vision task is still running.
        // 当另一个Vision任务正在运行时,不要将新的buffers添加到队列中
        // The camera stream has only a finite amount of buffers available; holding too many buffers for analysis would starve the camera.
        // 相机stream只有一个有限数量的buffers;持有太多buffers来分析,将会卡住相机.
        guard currentBuffer == nil, case .normal = frame.camera.trackingState else {
            return
        }

        // Retain the image buffer for Vision processing.
        // 强引用图片buffer以供Vision处理.
        self.currentBuffer = frame.capturedImage
        classifyCurrentImage()
    }

    // Run the Vision+ML classifier on the current image buffer.
    // 在当前图片buffer上运行Vision+ML分类器.
    /// - Tag: ClassifyCurrentImage
    private func classifyCurrentImage() {
        // Most computer vision tasks are not rotation agnostic so it is important to pass in the orientation of the image with respect to device.
        // 大部分计算型vision任务需要明确知道图片的朝向信息,所以需要将当前图片的朝向传入.
        let orientation = CGImagePropertyOrientation(UIDevice.current.orientation)

        let requestHandler = VNImageRequestHandler(cvPixelBuffer: currentBuffer!, orientation: orientation)
        visionQueue.async {
            do {
                // Release the pixel buffer when done, allowing the next buffer to be processed.
                // 处理完成后释放pixel buffer,允许处理下一个buffer.
                defer { self.currentBuffer = nil }
                try requestHandler.perform([self.classificationRequest])
            } catch {
                print("Error: Vision request failed with error \"\(error)\"")
            }
        }
    }

其中比较重要的就是:

  1. 一次只处理一个buffer;
  2. Vision在处理图片时需要传入朝向信息;

另外,如果你对Vision框架不熟悉的话,可能不知道:Vision框架中有一个专门的类,可以处理Core ML模型,这大大增强了Vision框架的使用范围,不止能完成默认的人脸识别,二维码识别,矩形识别等,还可以使用自己或别人训练出的任意ML模型,简直是神器!!

如果你不知道的话,相关代码如下,非常简单:

top Created with Sketch.