获取VNDetectTextRectanglesRequest完成处理程序上的VNImageRequestHandler中使用的cvPixelBuffer

时间:2017-07-25 09:00:40

标签: ios swift swift3 apple-vision

我正在使用以下代码创建我的请求:

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

在我的 AVCaptureVideoDataOutputSampleBufferDelegate 中,我正在创建一个VNImageRequestHandler并执行它:

let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation: CGImagePropertyOrientation(rawValue: 6)!, options: requestOptions)

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

这为我提供了具有以下签名的处理程序内的检测结果:

func detectTextHandler(request: VNRequest, error: Error?)

我的问题是,我怎样才能获得" cvPixelBuffer"该请求用于进一步处理?我应该存储它的时间版本吗?

3 个答案:

答案 0 :(得分:2)

我找不到从CVPixelBuffer检索VNRequest的任何方法或属性。

因此,在completionHandler的闭包内捕获它将是一个简单的方法:

AVCaptureVideoDataOutputSampleBufferDelegate的方法中:

    let pixelBuffer = ...
    let requestOptions: [VNImageOption: Any] = ...

    let textRequest = VNDetectTextRectanglesRequest {request, error in
        //### Capture `pixelBuffer` inside this closure.
        self.detectText(from: pixelBuffer, request: request, error: error)
    }
    textRequest.reportCharacterBoxes = true

    let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation: CGImagePropertyOrientation(rawValue: 6)!, options: requestOptions)

    do {
        try imageRequestHandler.perform([textRequest])
    } catch {
        print(error)
    }

并将其用作:

func detectText(from buffer: CVPixelBuffer, request: VNRequest, error: Error?) {
    //### Use `buffer` passed from the closure.
    //...
}

答案 1 :(得分:0)

这是一个很好的问题。

我的app(https://github.com/snakajima/MobileNet-iOS)遇到了类似的问题,需要保留对CMSampleBuffer对象的引用,直到调用完成处理程序为止(以便关联的pixelBuffer不会被重用)视频捕捉会议。)

我通过将其存储为视图控制器(self.sampleBuffer)的属性来解决它。结果,它一次只能处理一个pixelBuffer - 这对我的应用程序来说很好但不是最佳的。

如果你需要进行双缓冲(或更多),你需要引入一个(pixelBuffers)队列,假设完成的顺序与请求相同 - 这是考虑底层架构的合理假设。

答案 2 :(得分:0)

https://github.com/maxvol/RxVision使您无需重新创建每张图片的请求即可轻松完成操作(如接受的答案一样)。

let mlRequest: RxVNCoreMLRequest<CGImage> = VNCoreMLRequest.rx.request(model: model, imageCropAndScaleOption: .scaleFit)

mlRequest
    .observable
    .subscribe { [unowned self] (event) in
        switch event {
            case .next(let completion):       
                let cgImage = completion.value // NB you can easily pass the value along to the completion handler 
                if let result = completion.request.results?[0] as? VNClassificationObservation {
                    os_log("results: %@", type: .debug, result.identifier)
                }
            default:
                break
        }
    }
    .disposed(by: disposeBag)

let imageRequestHandler = VNImageRequestHandler(cgImage: cgImage, orientation: .up, options: requestOptions)
do {
    try imageRequestHandler.rx.perform([mlRequest], with: cgImage) // NB you can easily pass the value along to the completion handler
} catch {
    print(error)
}