使用 Vision 框架跟踪本地视频中的人脸 [关闭]

Posted

技术标签:

【中文标题】使用 Vision 框架跟踪本地视频中的人脸 [关闭]【英文标题】:Track faces in Local video using Vision framework [closed] 【发布时间】:2017-12-02 10:52:22 【问题描述】:

我正在尝试使用 Vision 框架检测本地录制视频中的人脸。提供的大多数示例都是在 Live cam 视频中检测人脸。

如何在本地视频中进行人脸检测,并在运行时使用 Vision/CoreML 框架在检测到的人脸中放置一个矩形?

【问题讨论】:

【参考方案1】: 等待您的 videoItem 准备好播放 向其添加输出 添加一个周期性的观察者,它应该在每一帧都被 ping 通 提取新的像素缓冲区并根据需要在 Vision / CoreML 中处理它们: 如果您使用视觉框架,您希望使用VNSequenceRequestHandler 而不是VNImageRequestHandler

.

import UIKit
import AVFoundation
import CoreML
import Vision

class ViewController: UIViewController 
  var player: AVPlayer!
  var videoOutput: AVPlayerItemVideoOutput?

  override func viewDidLoad() 
    super.viewDidLoad()

    let player = AVPlayer(url: localURL)
    player.play()

    player.currentItem?.addObserver(
      self,
      forKeyPath: #keyPath(AVPlayerItem.status),
      options: [.initial, .old, .new],
      context: nil)
    player.addPeriodicTimeObserver(
      forInterval: CMTime(value: 1, timescale: 30),
      queue: DispatchQueue(label: "videoProcessing", qos: .background),
      using:  time in
        self.doThingsWithFaces()
    )
    self.player = player
  

  override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) 
    guard let keyPath = keyPath, let item = object as? AVPlayerItem
      else  return 

    switch keyPath 
    case #keyPath(AVPlayerItem.status):
      if item.status == .readyToPlay 
        self.setUpOutput()
      
      break
    default: break
    
  

  func setUpOutput() 
    guard self.videoOutput == nil else  return 
    let videoItem = player.currentItem!
    if videoItem.status != AVPlayerItemStatus.readyToPlay 
      // see https://forums.developer.apple.com/thread/27589#128476
      return
    

    let pixelBuffAttributes = [
      kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange,
      ] as [String: Any]

    let videoOutput = AVPlayerItemVideoOutput(pixelBufferAttributes: pixelBuffAttributes)
    videoItem.add(videoOutput)
    self.videoOutput = videoOutput
  

  func getNewFrame() -> CVPixelBuffer? 
    guard let videoOutput = videoOutput, let currentItem = player.currentItem else  return nil 

    let time = currentItem.currentTime()
    if !videoOutput.hasNewPixelBuffer(forItemTime: time)  return nil 
    guard let buffer = videoOutput.copyPixelBuffer(forItemTime: time, itemTimeForDisplay: nil)
      else  return nil 
    return buffer
  

  func doThingsWithFaces() 
    guard let buffer = getNewFrame() else  return 
    // some CoreML / Vision things on that.
    // There are numerous examples with this
  

【讨论】:

我似乎让它工作得很好,但是当我有一个 AVPlayerLayer 来显示视频时,它就不再显示了。 嗨亚瑟 :) 你的意思是一旦你显示它打破的视频?你知道什么时候事情会变得奇怪吗? 我使用与您相同的 ViewDidLoad(复制粘贴),但是当我添加此代码时它停止工作: playerLayer = AVPlayerLayer(player: player) playerLayer.frame = CGRect(x: 0, y: 100 , 宽度: 300, 高度: 170) self.view.layer.addSublayer(playerLayer) 当我评论 player.currentItem?.addObserver 方法时,它会显示 AVPlayerLayer,但是,我没有得到观察者:D 这是因为这个例子一遍又一遍地添加了videoOutput。尝试 switch keyPath case #keyPath(AVPlayerItem.status): if item.status == .readyToPlay && self.videoOutput == nil self.setUpOutput() break

以上是关于使用 Vision 框架跟踪本地视频中的人脸 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Apple Vision Framework 识别人脸

CoreML Vision 人脸检测的输入图像尺寸要求是啥

使用 Vision 和 AVFoundation 框架从实时摄像头(而非静态图像)进行实时人脸检测

视频中减去帧的人脸跟踪

在相机源 + Vision API iOS11 上跟踪面部对象

将Vision人脸检测VNFaceLandmarkRegion2D点转换为要缩放的帧坐标