代码之家  ›  专栏  ›  技术社区  ›  Andy Jazz

在指定的时间段内运行并暂停会话

  •  -7
  • Andy Jazz  · 技术社区  · 6 年前

    我在发展 ARKit / Vision UIView . 没有 ARSCNView ARSKView ARFrames 进入 CVPixelBuffer 那我用什么呢 VNRecognizedObjectObservation .

    currentFrame.capturedImage 对于 像素缓冲区

    preferredFramesPerSecond 实例属性在我的例子中是绝对无用的,因为它控制渲染对象的帧速率 ARSCNView / 阿什克维尤 . 我没有意见。而且它不会影响会话的帧速率。

    run() pause() 方法来降低会话的帧速率。

    问题

    我想知道如何自动 run pause 暂停 16 ms (或0.016秒)。我想这可能是通过 DispatchQueue . 但我不知道如何实现它。

    enter image description here

    session.run(configuration)
    
        /*  run lasts 16 ms  */
    
    session.pause()
    
        /*  pause lasts 16 ms  */
    
    session.run(session.configuration!)
    
        /*  etc...  */
    

    附笔。 我的应用程序中既不能使用CocoaPod也不能使用Carthage

    使现代化 当前位置是关于ARSession的 currentFrame.capturedImage 检索并使用。

    let session = ARSession()
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
    
        session.delegate = self
        let configuration = ARImageTrackingConfiguration() // 6DOF
        configuration.providesAudioData = false
        configuration.isAutoFocusEnabled = true            
        configuration.isLightEstimationEnabled = false
        configuration.maximumNumberOfTrackedImages = 0
        session.run(configuration)  
    
        spawnCoreMLUpdate()
    }
    
    func spawnCoreMLUpdate() {    // Spawning new async tasks
    
        dispatchQueue.async {
            self.spawnCoreMLUpdate()
            self.updateCoreML()
        }
    }
    
    func updateCoreML() {
    
        let pixelBuffer: CVPixelBuffer? = (session.currentFrame?.capturedImage)
        if pixelBuffer == nil { return }
        let ciImage = CIImage(cvPixelBuffer: pixelBuffer!)
        let imageRequestHandler = VNImageRequestHandler(ciImage: ciImage, options: [:])
        do {
            try imageRequestHandler.perform(self.visionRequests)
        } catch {
            print(error)
        }
    }
    
    3 回复  |  直到 5 年前
        1
  •  5
  •   EmilioPelaez    6 年前

    如果要将帧速率从60降低到30,则应使用 preferredFramesPerSecond 性质 SCNView ARSCNView ,它是 SCNView .

    Property documentation.

        2
  •  3
  •   Sparga    6 年前

    我不认为 run() pause() 由于DispatchQueue API不是为实时准确性而设计的,因此策略是一种可行的方法。这意味着无法保证每次暂停时间为16毫秒。除此之外,重新启动会话可能不是立即的,并且可能会增加更多的延迟。

    session.run(configuration) 是异步的,可能不会捕获任何帧。

    因为你没有使用 ARSCNView/ARSKView 唯一的办法是实施 ARSession 每个捕获的帧都将通知代理。

    这里有一些代码可以帮助您开始,请确保 dispatchQueue 不能同时按顺序处理缓冲区:

    var lastProcessedFrame: ARFrame?
    
    func session(_ session: ARSession, didUpdate frame: ARFrame) {
      dispatchQueue.async {
        self.updateCoreML(with: frame)
      }
    }
    
    private func shouldProcessFrame(_ frame: ARFrame) -> Bool {
      guard let lastProcessedFrame = lastProcessedFrame else {
        // Always process the first frame
        return true
      }
      return frame.timestamp - lastProcessedFrame.timestamp >= 0.032 // 32ms for 30fps
    }
    
    func updateCoreML(with frame: ARFrame) {
    
      guard shouldProcessFrame(frame) else {
        // Less than 32ms with the previous frame
        return
      }
      lastProcessedFrame = frame
      let pixelBuffer = frame.capturedImage
      let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:])
      do {
        try imageRequestHandler.perform(self.visionRequests)
      } catch {
        print(error)
      }
    }
    
        3
  •  1
  •   Emre Önder    6 年前

    let syncConc = DispatchQueue(label:"con",attributes:.concurrent)
    
    DispatchQueue.global(qos: .utility).async {
    syncConc.async {
        for _ in 0...10{
            print("HHH - \(Thread.current)")
            Thread.sleep(forTimeInterval: 1)
            print("ABC - \(Thread.current)")
    
        }
    }
    

    PS:我仍然不确定Thread.sleep是否会阻止您的进程,如果是,我将编辑我的答案。