将 12 个 ARFrame 添加到 Array (iOS/Swift) 后 ARSCNView 冻结

Posted

技术标签:

【中文标题】将 12 个 ARFrame 添加到 Array (iOS/Swift) 后 ARSCNView 冻结【英文标题】:ARSCNView freezes after adding 12 ARFrame to Array (iOS/Swift) 【发布时间】:2018-12-25 20:08:39 【问题描述】:

我在ViewController.swift 中有一个ARSCNView,我想将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
        
    

【问题讨论】:

【参考方案1】:

每个ARFrame 都包含一个直接来自摄像头捕获系统的视频帧(在其capturedImage 属性中)。

捕获系统提供的每个帧都来自一个固定大小的内存池,捕获系统会在会话继续时重复使用这些内存池。如捕获docs中所述:

如果多个样本缓冲区引用此类内存池的时间过长,输入将不再能够将新样本复制到内存中,并且这些样本将被丢弃。

如果您的应用程序由于保留提供的 CMSampleBuffer 对象太久而导致样本被丢弃,但它需要长时间访问样本数据,请考虑将数据复制到新缓冲区中,然后释放样本缓冲区(如果它以前被保留),以便它引用的内存可以被重用。

通过将所有ARFrames 添加到一个数组中,您就声称拥有(即保留)其像素缓冲区的所有权,并最终使内存捕获系统无法写入新帧。ARKit 需要一个连续的流视频,所以你的 AR 会话放弃了。

解决方案?不要抓住所有这些框架。仅将您需要的任何信息从每一帧复制到您自己的数据结构中。

【讨论】:

非常感谢,我真的不知道这一点。 我认为 ARKit 文档中有关于此的内容,但找不到。但是文档上file bugs 的人越多越好,对吧? 嗨@rickster 我正在做同样的事情,将帧附加到数组并遇到 12 帧限制。我不确定复制和释放样本缓冲区的含义?您的意思是创建一个新的 CVPixelBuffer 变量并将 ARFrame.captureimage 存储在其中吗?感谢您的宝贵时间! @mikey 不,您需要实际复制像素缓冲区数据。见this question。 谢谢@rickster 我最终使用了gist.github.com/humblehacker/a55db40791605c4e40411f70bcd13d13 之类的扩展名,完成后可能会发布答案

以上是关于将 12 个 ARFrame 添加到 Array (iOS/Swift) 后 ARSCNView 冻结的主要内容,如果未能解决你的问题,请参考以下文章

ARKit:ARFrame.timestamp 代表啥?

将 bash 脚本添加到路径

銆學arframe鐑慨銆嶈繙鍙や箣琛€锛圱he Old Blood锛夛細Hotfix 26.0.5

GREP未检测到数组中添加的元素

如何将Rectangle添加到Array中?

PHP使用array_push将元素添加到多维数组