结合 CoreML 对象检测和 ARKit 2D 图像检测

Posted

技术标签:

【中文标题】结合 CoreML 对象检测和 ARKit 2D 图像检测【英文标题】:Combining CoreML Object Detection and ARKit 2D Image Detection 【发布时间】:2020-03-10 13:07:19 【问题描述】:

该应用程序检测特定的 2D 图像(使用 ARKit)并有一个检测一些家具的 mlmodel,mlmodel 的类型是对象检测,它经过训练并且可以工作。根据检测到的内容,我需要将一些 3D 对象添加到场景或其他对象中。

我使用 ARWorldTrackingConfiguration 创建了一个 AR 会话,我可以检测到 2D 图像,并在方法 renderer(_:didAdd:for:) 中添加了 3D 对象,它运行良好:

    override func viewDidAppear(_ animated: Bool) 
    super.viewWillAppear(animated)

    guard let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else 
        fatalError("Missing expected asset catalog resources.")
    

    let configuration = ARWorldTrackingConfiguration()
    configuration.worldAlignment = .gravityAndHeading
    configuration.detectionImages = referenceImages
    configuration.maximumNumberOfTrackedImages = 1
    configuration.isAutoFocusEnabled = false
    sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])

另外,我设置了 mlmodel:

override func viewDidLoad() 

    super.viewDidLoad()
    sceneView.delegate = self
    sceneView.session.delegate = self
    setupML()


    internal func setupML() 

    guard let modelPath = Bundle.main.url(forResource: "furnituresDetector", withExtension: "mlmodelc") else 
        fatalError("Missing model")
    

    do 
        let coreMLModel = try VNCoreMLModel(for: MLModel(contentsOf: modelPath))
        let request = VNCoreMLRequest(model: coreMLModel)  [weak self] (request, error) in
            DispatchQueue.main.async 
                if let results = request.results 
                    print(results.count)
                
            
        
        self.requests = [request]
     catch 
        print("Core ML Model error")
    

此时我只想打印结果的数量以查看 ml 模型是否检测到某些东西。

直到这里一切正常,我运行应用程序并且相机显示流畅。正如我在 Combining CoreML and ARKit 中找到的那样,我重用了由 ARSCNView 启动的会话,而不是创建一个新的相机会话。

所以我的解决方案是使用 session(_:didUpdate:) 向 coreml 模型发出请求,并不断知道模型是否检测到相机中出现的东西。

    func session(_ session: ARSession, didUpdate frame: ARFrame) 

    DispatchQueue(label: "CoreML_request").async 
        guard let pixelBuffer = session.currentFrame?.capturedImage else 
            return
        

        let exifOrientation = self.exifOrientationFromDeviceOrientation()


        let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation: exifOrientation, options: [:])
        do 
            try imageRequestHandler.perform(self.requests)
         catch 
            print(error)
        
    

如果我运行该应用程序,它可以工作,但问题是摄像头看起来很慢,如果我删除 session(_:didUpdate:) 中的代码,摄像头看起来又正常了。所以问题就在这里,我想发生的事情是它不是发出这个请求的正确位置,因为当检测到相机中的新帧时,这个方法一直被调用。 但我不知道在哪里提出请求或做什么。你有什么想法吗?

如果我找到一些解决方案,我会更新它。 谢谢!

【问题讨论】:

您的 Core ML 模型可能太大且速度太慢,无法跟上相机的速度。一个简单的解决方案是减少运行 Core ML 模型的频率。 【参考方案1】:

我找到了解决方案。问题是相机的可用缓冲区有限,当另一个 Vision 任务仍在运行时,我将太多缓冲区排入队列。

这就是相机速度慢的原因。因此,解决方案是在执行另一个请求之前释放缓冲区。

internal var currentBuffer: CVPixelBuffer?

func session(_ session: ARSession, didUpdate frame: ARFrame) 

    guard currentBuffer == nil, case .normal = frame.camera.trackingState else 
        return
    
    self.currentBuffer = frame.capturedImage

    DispatchQueue(label: "CoreML_request").async 
        guard let pixelBuffer = session.currentFrame?.capturedImage else 
            return
        

        let exifOrientation = self.exifOrientationFromDeviceOrientation()

        let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation: exifOrientation, options: [:])
        do 
            // Release the pixel buffer when done, allowing the next buffer to be processed.
            defer  self.currentBuffer = nil 
            try imageRequestHandler.perform(self.requests)
         catch 
            print(error)
        
    

您可以在这里查看文档:

https://developer.apple.com/documentation/arkit/recognizing_and_labeling_arbitrary_objects

【讨论】:

以上是关于结合 CoreML 对象检测和 ARKit 2D 图像检测的主要内容,如果未能解决你的问题,请参考以下文章

使用 ARKit 和 CoreML 从远距离检测物体

结合 CoreML 和 ARKit

是否可以使用 CoreML 模型检测对象并找到该对象的测量值?

ARKit 和视觉框架——检测墙壁边缘

带有 ARkit 和 CoreML 的视觉框架

CoreML:iOS:如何获取检测模型中心的 2D 坐标