Информация о кадре в обработчике завершения для обнаружения текста в ARSession - PullRequest
2 голосов
/ 21 мая 2019

Я использую 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 Ответ

1 голос
/ 21 мая 2019

Почему бы вам не использовать свойство 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 ) 
    ...
}

Вы также можете использовать currentFrame для создания обработчика запроса изображения в session(_:didUpdate:):

let pixelBuffer = sceneView.currentFrame.capturedImage

Также обратите внимание, что запуск perform() метода VNImageRequestHandler в session(_:didUpdate:) неэффективен и занимает столько времени, поскольку он выполняется постоянно, вместо этого можно использовать Timer, чтобы сократить количество выполняемых вами операций.процесс обнаружения изображений.


Редактировать: Поскольку обнаружение изображения является асинхронным и может потребоваться время для завершения, вы можете сохранить кадр в другом экземпляре при выполнении запроса и использовать этот экземпляр в обработчике завершения:

var detectionFrame: ARFrame?

// Timer block
detectionFrame = sceneView.session.currentFrame
let pixelBuffer = detectionFrame.capturedImage
// image detection request code


func detectTextHandler(request: VNRequest, error: Error?) {
    guard let frame = detectionFrame else { return }
    ...
    let hit = frame.hitTest(box?.topRight - box?.bottomLeft, types: ARHitTestResult.ResultType.featurePoint ) 
    ...
}
...