首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ARKit:跟踪VisonCoreML检测到的对象

ARKit:跟踪VisonCoreML检测到的对象
EN

Stack Overflow用户
提问于 2022-08-02 10:44:32
回答 1查看 93关注 0票数 0

我是iOS新手,目前正在重构从VisionCoreML和ARKit教程获得的代码,该教程向检测到的对象添加了一个节点。

当前,如果i移动对象,则节点不会移动并跟踪该对象。我可以从苹果的在实时捕获中识别对象示例代码中看到,每当Vision在一个新的位置检测到对象时,他们就会使用图层并重新定位,这正是我希望用ARObject复制的。

有什么方法可以用ARKit实现这一点吗?

这方面的任何帮助都将不胜感激。谢谢。

编辑:使用解决方案的工作代码

代码语言:javascript
运行
复制
@IBOutlet var sceneView: ARSCNView!
private var viewportSize: CGSize!
private var previousAnchor: ARAnchor?
private var trackingNode: SCNNode!
lazy var objectDetectionRequest: VNCoreMLRequest = {
    do {
        let model = try VNCoreMLModel(for: yolov5s(configuration: MLModelConfiguration()).model)
        let request = VNCoreMLRequest(model: model) { [weak self] request, error in
            self?.processDetections(for: request, error: error)
        }
        return request
    } catch {
        fatalError("Failed to load Vision ML model.")
    }
}()

func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval) {
    guard let capturedImage = sceneView.session.currentFrame?.capturedImage
    else { return }
    
    let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: capturedImage, orientation: .leftMirrored, options: [:])
    
    do {
        try imageRequestHandler.perform([objectDetectionRequest])
    } catch {
        print("Failed to perform image request.")
    }
}

func processDetections(for request: VNRequest, error: Error?) {
    guard error == nil else {
        print("Object detection error: \(error!.localizedDescription)")
        return
    }
    
    guard let results = request.results else { return }
    
    for observation in results where observation is VNRecognizedObjectObservation {
        
        let objectObservation = observation as! VNRecognizedObjectObservation
        let topLabelObservation = objectObservation.labels.first
        print(topLabelObservation!.identifier + " " + "\(Int(topLabelObservation!.confidence * 100))%")
        guard recognisedObject(topLabelObservation!.identifier) && topLabelObservation!.confidence > 0.9
            else { continue }

        let rect = VNImageRectForNormalizedRect(
            objectObservation.boundingBox,
            Int(self.sceneView.bounds.width),
            Int(self.sceneView.bounds.height))
        
        let midPoint = CGPoint(x: rect.midX, y: rect.midY)
        
        let raycastQuery = self.sceneView.raycastQuery(from: midPoint,
                                                  allowing: .estimatedPlane,
                                                  alignment: .any)
        let raycastArray = self.sceneView.session.raycast(raycastQuery!)
        guard let raycastResult = raycastArray.first else { return }
        
        let position = SCNVector3(raycastResult.worldTransform.columns.3.x,
                                raycastResult.worldTransform.columns.3.y,
                                raycastResult.worldTransform.columns.3.z)
        
        if let _ = trackingNode {
            trackingNode!.worldPosition = position
        } else {
            trackingNode = createNode()
            trackingNode!.worldPosition = position
            self.sceneView.scene.rootNode.addChildNode(trackingNode!)
        }
    }
}

private func recognisedObject(_ identifier: String) -> Bool {
    return identifier == "remote" || identifier == "mouse"
}

private func createNode() -> SCNNode {
    let sphereNode = SCNNode(geometry: SCNSphere(radius: 0.01))
    sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.purple
    
    return sphereNode
}

private func loadSession() {
    let configuration = ARWorldTrackingConfiguration()
    configuration.planeDetection = []
    sceneView.session.run(configuration)
}


override func viewDidLoad() {
    super.viewDidLoad()
    sceneView.delegate = self
    viewportSize = sceneView.frame.size
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    loadSession()
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    sceneView.session.pause()
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-02 18:50:38

老实说,你在这里使用的技术不能开箱即用。YOLO (以及您换掉的任何其他对象检测模型)没有内置跟踪视频中相同对象的概念。它们在2D位图中查找对象,并为它们返回2D边界框。当相机或对象移动时,通过下一个capturedImage缓冲区,它将为您提供一个位于正确位置的新的边界框,但它无法知道是否是在前一个帧中检测到的对象的同一个实例。

要做到这一点,您需要对这些Vision结果进行一些后处理,以确定它是否是同一个对象,如果是的话,手动移动锚/网格以匹配新位置。如果您确信在任何时候只应该有一个对象在视图中,那么这是非常简单的。如果有多个对象,您将冒险进入复杂(但仍可实现)的领域。

您可以尝试合并视觉跟踪,但这可能会根据跟踪对象的性质和行为而起作用。

另外,sceneView.hitTest()也不受欢迎。您可能应该将其移植到使用ARSession.raycast()

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73206186

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档