我在ARSCNView中有一个ViewController.swift,我想将ARFrames保存到一个预先分配的数组中

func session(_ session: ARSession, didUpdate frame: ARFrame)

但是,在处理了大约11-13 ARFrames之后,整个ARSCNView将通过使用冻结
self.ARFrames.append(frame)

奇怪的是,在此过程中未调用func session(_ session: ARSession, didFailWithError error: Error),也未报告任何其他错误,该应用程序不会崩溃,并且其他所有用户控件均正常运行,仅ARSCNView冻结和didpUdate事件不会被调用。与ARSCNView freezes when adding 14 ARAnchor subclass objects with strong reference类似,但是那里的页面没有解决方案。同样,在应用程序返回后台并返回后,即使场景视图之前已冻结,也会调用sessionWasInterrupted(:)sessionInterruptionEnded(:)这是iOS 11的错误吗?

这是我在应用程序中使用的完整代码。
import UIKit

class ViewController: UIViewController,ARSCNViewDelegate,ARSessionDelegate {
    @IBOutlet var sceneView: ARSCNView!
    let configuration = ARFaceTrackingConfiguration()
    var ARFrames = [ARFrame]()
    var imgCount = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        ARFrames.reserveCapacity(300)
        sceneView.delegate = self
        sceneView.session.delegate = self
        sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
    }

    func session(_ session: ARSession, didUpdate frame: ARFrame) {
        if (frame.capturedDepthData == nil || self.imgCount >= 300){
            return
        }
        DispatchQueue.global().async {
            self.ARFrames.append(frame)
            self.imgCount += 1
        }
    }
}

最佳答案

每个ARFrame都包含一个直接来自摄像机捕获系统的视频帧(在其 capturedImage 属性中)。
捕获系统出售的每个帧都来自固定大小的内存池,捕获系统会在 session 继续时重用这些内存。如捕获docs中所述:

如果多个样本缓冲区引用此类内存池的时间过长,则输入将不再能够将新样本复制到内存中,并且这些样本将被丢弃。
如果您的应用程序由于将提供的CMSampleBuffer对象保留太长时间而导致删除样本,但是它需要长时间访问样本数据,请考虑将数据复制到新缓冲区中,然后释放样本缓冲区(如果之前已保留),以便可以重用它引用的内存。

通过将所有获得的ARFrame添加到数组中,您可以声明(即保留)其像素缓冲区的所有权,并最终使内存的捕获系统饿死以写入新帧。ARKit需要连续的视频流,因此您的AR session 放弃了。
解决方案?不要抓住所有这些框架。仅将每个框架中需要的任何信息复制到自己的数据结构中。

关于ios - 将12 ARFrame添加到阵列(iOS/Swift)后,ARSCNView卡住,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51392963/

10-11 19:50