ARSession 中用于文本检测的完成处理程序中的帧信息
Frame information in completion handler for text detection in ARSession
我正在使用 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({[=10=] 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)
}
}
我可以保留一本字典并查找它,但它不是很优雅,而且容易出现错误和泄漏。我宁愿通过我请求文本检测的相关框架。
有什么想法吗?
为什么不在完成处理程序中使用会话的 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
此外,请注意,在 session(_:didUpdate:)
中触发 VNImageRequestHandler
的 perform()
方法效率不高,并且需要很多过程,因为它一直是 运行,您可以使用a 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 )
...
}
我正在使用 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({[=10=] 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)
}
}
我可以保留一本字典并查找它,但它不是很优雅,而且容易出现错误和泄漏。我宁愿通过我请求文本检测的相关框架。
有什么想法吗?
为什么不在完成处理程序中使用会话的 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
此外,请注意,在 session(_:didUpdate:)
中触发 VNImageRequestHandler
的 perform()
方法效率不高,并且需要很多过程,因为它一直是 运行,您可以使用a 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 )
...
}