完成处理程序中的框架信息,用于在ARSession

时间:2019-05-21 09:00:19

标签: ios swift computer-vision arkit apple-vision

我正在使用Core Vision在ARKit会话中检测文本框,一旦检测到文本框,我的问题是访问frame进行命中测试。

func startTextDetection() {
    let textRequest = VNDetectTextRectanglesRequest(completionHandler: self.detectTextHandler)
    textRequest.reportCharacterBoxes = true
    self.requests = [textRequest]
}

func detectTextHandler(request: VNRequest, error: Error?) {
    guard let observations = request.results else {
        print("no result")
        return
    }

    let result = observations.map({$0 as? VNTextObservation})
    for box in result {
        let hit = frame.hitTest(box?.topRight - box?.bottomLeft, types: ARHitTestResult.ResultType.featurePoint )
        let anchor = ARAnchor(transform:hit.worldTransform)
        sceneView.session.add(anchor:anchor)
    }
    //DispatchQueue.main.async() {

    //}
}

理想情况下,我会从ARSession委托方法将其传递给完成处理程序,但是尽管文档说我可以在此处传递完成处理程序,但我没有找到一种方法。

func session(_ session: ARSession, didUpdate frame: ARFrame) {
    // Retain the image buffer for Vision processing.
    let pixelBuffer = frame.capturedImage
    let requestOptions:[VNImageOption : Any] = [:]

    let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation: CGImagePropertyOrientation.up, options: requestOptions)

    do {
        try imageRequestHandler.perform(self.requests)
    } catch {
        print(error)
    }
}

我可以保留一本字典并查找它,但它并不真正优雅,并且容易出现错误和泄漏。我宁愿在请求文本检测的地方传递相关的框架。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您为什么不在完成处理程序中使用会话的currentFrame属性?它包含会话的当前框架。另外,您无需再将任何frame实例传递给完成处理程序。只需使用您的sceneView实例即可访问。

因此,您可以像下面那样更改完成处理程序:

func detectTextHandler(request: VNRequest, error: Error?) {
    guard let currentFrame = sceneView.session.currentFrame else { return }
    ...
    // perform hit test using currentFrame
    let hit = currentFrame.hitTest(box?.topRight - box?.bottomLeft, types: ARHitTestResult.ResultType.featurePoint ) 
    ...
}

您也可以使用currentFramesession(_:didUpdate:)中创建图像请求处理程序:

let pixelBuffer = sceneView.currentFrame.capturedImage

还要注意,在perform()中触发VNImageRequestHandler的{​​{1}}方法效率不高,而且由于它一直在运行,因此需要花费大量的时间,您可以使用session(_:didUpdate:)相反,为了减少执行图像检测过程的时间。


编辑:由于图像检测是异步的,可能需要一些时间才能完成,因此您可以在发出请求时将帧存储在另一个实例中,并在完成处理程序中使用该实例:

Timer