获取在 VNDetectTextRectanglesRequest 完成处理程序上的 VNImageRequestHandler 中使用的 cvPixelBuffer
Get the cvPixelBuffer used in a VNImageRequestHandler on the VNDetectTextRectanglesRequest completion handler
我正在使用以下代码创建我的请求:
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"?我应该存储它的临时版本吗?
我找不到任何方法或属性来从 VNRequest
检索 CVPixelBuffer
。
因此,在 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.
//...
}
这是个好问题。
我的应用 (https://github.com/snakajima/MobileNet-iOS) 遇到了类似的问题,它需要保留对 CMSampleBuffer 对象的引用,直到调用完成处理程序(这样关联的 pixelBuffer 才不会被重用通过视频捕获会话)。
我通过将其存储为视图控制器 (self.sampleBuffer) 的 属性 来解决它。因此,它一次只能处理一个 pixelBuffer——这对我的应用程序来说很好,但不是最优的。
如果你需要做双缓冲(或更多),你需要引入一个队列(pixelBuffers),假设完成的顺序与请求相同——考虑到底层架构,这是合理的假设。
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)
}
我正在使用以下代码创建我的请求:
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"?我应该存储它的临时版本吗?
我找不到任何方法或属性来从 VNRequest
检索 CVPixelBuffer
。
因此,在 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.
//...
}
这是个好问题。
我的应用 (https://github.com/snakajima/MobileNet-iOS) 遇到了类似的问题,它需要保留对 CMSampleBuffer 对象的引用,直到调用完成处理程序(这样关联的 pixelBuffer 才不会被重用通过视频捕获会话)。
我通过将其存储为视图控制器 (self.sampleBuffer) 的 属性 来解决它。因此,它一次只能处理一个 pixelBuffer——这对我的应用程序来说很好,但不是最优的。
如果你需要做双缓冲(或更多),你需要引入一个队列(pixelBuffers),假设完成的顺序与请求相同——考虑到底层架构,这是合理的假设。
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)
}