我正在开发具有Vision框架功能(处理CoreML模型)的ARKit应用。
loopCoreMLUpdate()
函数产生一个循环,导致非常高的能量影响(CPU = 70%,GPU = 66%)。
如何处理此任务并将能源影响降低到低水平?
此循环问题的解决方法是什么,它将帮助我减少CPU / GPU工作量?
这是我的代码:
import UIKit
import SpriteKit
import ARKit
import Vision
class ViewController: UIViewController, ARSKViewDelegate {
@IBOutlet weak var sceneView: ARSKView!
let dispatchQueueML = DispatchQueue(label: "AI")
var visionRequests = [VNRequest]()
// .........................................
// .........................................
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let configuration = AROrientationTrackingConfiguration()
sceneView.session.run(configuration)
loopCoreMLUpdate()
}
func loopCoreMLUpdate() {
dispatchQueueML.async {
self.loopCoreMLUpdate() // SELF-LOOP LEADS TO A VERY HIGH IMPACT
self.updateCoreML()
}
}
func updateCoreML() {
let piBuffer: CVPixelBuffer? = (sceneView.session.currentFrame?.capturedImage)
if piBuffer == nil { return }
let ciImage = CIImage(cvPixelBuffer: piBuffer!)
let imageRequestHandler = VNImageRequestHandler(ciImage: ciImage, options: [:])
do {
try imageRequestHandler.perform(self.visionRequests)
} catch {
print(error)
}
}
// .........................................
// .........................................
}
答案 0 :(得分:2)
是的,您标记的那行肯定是一个大问题。您不在这里循环;您会在上一个任务完成之前尽快生成新的异步任务。无论如何,您试图捕获CVPixelBuffers的速度要快于创建它们的时间,这是一个巨大的浪费。
如果要捕获帧,则无需创建紧密的循环来对其进行采样。您将自己设置为ARSessionDelegate并实现session(_:didUpdate:)
。系统将在有新框架时通知您。 (可以创建自己的渲染循环,但是您不必在这里这样做,除非您确实需要自己的渲染管道,否则不应该这样做。)
请记住,您将很快收到很多帧。 30fps或60fps很常见,但可以高达120fps。您不能使用所有的时间片(其他东西也需要处理器时间)。关键是您通常无法跟上帧速率,并且需要缓冲以备后用,或者丢弃帧,或两者兼而有之。这是实时处理的非常正常的部分。
对于这种分类系统,您可能希望选择实际的帧速率(可能低至10-20fps),并跳过帧以保持该速率。对数十个几乎相同的帧进行分类可能没有帮助。
也就是说,请确保您已阅读Recognizing Objects in Live Capture。感觉就是您要这样做,并且为此提供了很好的示例代码。