17-《ARKit by Tutorials》读书笔记4:面部识别AR

栏目: IOS · 发布时间: 6年前

内容简介:本文是Ray Wenderlich上《ARKit by Tutorials》的读书笔记,主要讲内容概要和读后感没错,本文主要讲iPhone X的前置TrueDepth摄像头的AR效果!主要功能:

ARKit系列文章目录

本文是Ray Wenderlich上《ARKit by Tutorials》的读书笔记,主要讲内容概要和读后感

没错,本文主要讲iPhone X的前置TrueDepth摄像头的AR效果!主要功能:

  • 面部检测和追踪
  • 实时面部表情追踪
  • 同时捕捉彩色图像,和深度图像
  • 光照估计
17-《ARKit by Tutorials》读书笔记4:面部识别AR

初始化配置

面部AR的启动和其他的差不多,只需要将配置项换成 ARFaceTrackingConfiguration() 就可以了,错误处理也类似:

func resetTracking() {
  // 1
  guard ARFaceTrackingConfiguration.isSupported else {
    updateMessage(text: "Face Tracking Not Supported.")
    return
  }

  // 2
  updateMessage(text: "Looking for a face.")

  // 3
  let configuration = ARFaceTrackingConfiguration()
  configuration.isLightEstimationEnabled = true /* default setting */
  configuration.providesAudioData = false /* default setting */

  // 4
  session.run(configuration, options: 
              [.resetTracking, .removeExistingAnchors])
}
复制代码
func session(_ session: ARSession, didFailWithError error: Error) {
  print("** didFailWithError")
  updateMessage(text: "Session failed.")
}

func sessionWasInterrupted(_ session: ARSession) {
  print("** sessionWasInterrupted")
  updateMessage(text: "Session interrupted.")
}

func sessionInterruptionEnded(_ session: ARSession) {
  print("** sessionInterruptionEnded")
  updateMessage(text: "Session interruption ended.")
}
复制代码

人脸追踪

ARKit在检测到人脸时,会添加一个 ARFaceAnchor 到场景中,我们就可以用这个锚点来实现定位和追踪功能.

如果有两张人脸,ARKit只会追踪最大,最具有辨识度的那张脸.同时会在人脸上添加一个人脸坐标系:

17-《ARKit by Tutorials》读书笔记4:面部识别AR
我们用scene的Metal device来创建人脸的几何体 ARSCNFaceGeometry ,并为其创建一个SCNNode对象 mask

来持有几何体:

func createFaceGeometry() {
  updateMessage(text: "Creating face geometry.")

  let device = sceneView.device!

  let maskGeometry = ARSCNFaceGeometry(device: device)!
  mask = Mask(geometry: maskGeometry)
}
复制代码

这个方法可以在 viewDidLoad 里面直接调用,无需等到人脸出现再创建.

最后将 mask 添加到视图上以显示出来:

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
  anchorNode = node
  //将mask显示出来
  setupFaceNodeContent()
}

func setupFaceNodeContent() {
  guard let node = anchorNode else { return }

  node.childNodes.forEach { $0.removeFromParentNode() }

  if let content = mask {
    node.addChildNode(content)
  }
}
复制代码

前面创建的几何体 ARSCNFaceGeometry 因为还没有识别到人脸,可能是空的.所以我们需要在后面的update方法中更新.

func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
  guard let faceAnchor = anchor as? ARFaceAnchor else { return }
  updateMessage(text: "Tracking your face.")
  // 根据锚点更新几何体
  mask?.update(withFaceAnchor: faceAnchor)
}
// Tag: ARFaceAnchor Update
func update(withFaceAnchor anchor: ARFaceAnchor) {
  let faceGeometry = geometry as! ARSCNFaceGeometry
  faceGeometry.update(from: anchor.geometry)
}
复制代码
17-《ARKit by Tutorials》读书笔记4:面部识别AR

默认情况下灯光设置是这样:

/* default settings */
sceneView.automaticallyUpdatesLighting = true 
sceneView.autoenablesDefaultLighting = false 
sceneView.scene.lightingEnvironment.intensity = 1.0 
复制代码

但我们也可以根据环境调整,以实现不同的效果:

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
  // 1
  guard let estimate = session.currentFrame?.lightEstimate else {
    return
  }

  // 2 在ARKit中1000意味着光强为中等
  let intensity = estimate.ambientIntensity / 1000.0
  sceneView.scene.lightingEnvironment.intensity = intensity

  // 3
  let intensityStr = String(format: "%.2f", intensity)
  let sceneLighting = String(format: "%.2f",
    sceneView.scene.lightingEnvironment.intensity)

  // 4
  print("Intensity: \(intensityStr) - \(sceneLighting)")
}
复制代码
17-《ARKit by Tutorials》读书笔记4:面部识别AR

blend shapes表情动画

如何实现Animojis中的表情动画效果呢?这就用到了blend shapes,它本质是一个字典,key是 ARFaceAnchor.BlendShapeLocation 常量,而value则是浮点数,范围0.0(自然状态)~1.0(最大移动状态).

比如,我们想添加一个眨眼的效果,取出 eyeBlinkLeft :

17-《ARKit by Tutorials》读书笔记4:面部识别AR

这个字典的是随着ARFaceAnchor更新而更新的:

// - Tag: ARFaceAnchor Update
func update(withFaceAnchor anchor: ARFaceAnchor) {
  blendShapes = anchor.blendShapes
}

// - Tag: BlendShapeAnimation
var blendShapes: [ARFaceAnchor.BlendShapeLocation: Any] = [:] {
  didSet {
    guard
      // Brow
      let browInnerUp = blendShapes[.browInnerUp] as? Float
      // Right eye
let eyeLookInRight = blendShapes[.eyeLookInRight] as? Float,
let eyeLookOutRight = blendShapes[.eyeLookOutRight] as? Float,
let eyeLookUpRight = blendShapes[.eyeLookUpRight] as? Float,
let eyeLookDownRight = blendShapes[.eyeLookDownRight] as? Float,
let eyeBlinkRight = blendShapes[.eyeBlinkRight] as? Float
      else { return }

    // 在处理动画
}
复制代码

实现后的效果

17-《ARKit by Tutorials》读书笔记4:面部识别AR

ReplayKit录像

ReplayKit是在iOS 9引入的,用来录制音频,视频和麦克风,主要有两个类:

  • RPScreenRecorder :用来启动/停止录制的单例.
  • RPPreviewViewController :录制完成后的预览控制器.
17-《ARKit by Tutorials》读书笔记4:面部识别AR
2017年又推出了 ReplayKit 2

:

  • iOS屏幕录制和广播
  • 广播配对
  • 快速摄像头切换
  • 应用内屏幕捕捉
17-《ARKit by Tutorials》读书笔记4:面部识别AR

开始录制

主要代码

let sharedRecorder = RPScreenRecorder.shared()
private var isRecording = false 
复制代码
// Private functions
private func startRecording() {
  // 1
  self.sharedRecorder.isMicrophoneEnabled = true

  // 2
  sharedRecorder.startRecording( handler: { error in
    guard error == nil else {
      print("There was an error starting the recording: \(String(describing: error?.localizedDescription))")
      return
    }

    // 3
    print("Started Recording Successfully")
    self.isRecording = true

    // 4
    DispatchQueue.main.async {
      self.recordButton.setTitle("[ STOP RECORDING ]", for: .normal)
      self.recordButton.backgroundColor = UIColor.red
    }
  })
} 
复制代码

停止录制

主要代码

func stopRecording() {
  // 1
  self.sharedRecorder.isMicrophoneEnabled = false

  // 2
  sharedRecorder.stopRecording( handler: { 
    previewViewController, error in
    guard error == nil else {
      print("There was an error stopping the recording: \(String(describing: error?.localizedDescription))")
      return
    }

    // 3
    if let unwrappedPreview = previewViewController {
      unwrappedPreview.previewControllerDelegate = self
      self.present(unwrappedPreview, animated: true, completion: {})
    }
  })

  // 4
  self.isRecording = false
  DispatchQueue.main.async {
    self.recordButton.setTitle("[ RECORD ]", for: .normal)
    self.recordButton.backgroundColor = UIColor(red: 0.0039, 
      green: 0.5882, blue: 1, alpha: 1.0) /* #0196ff */
  }
}
复制代码

效果如图:

17-《ARKit by Tutorials》读书笔记4:面部识别AR

另外,还可以实现 sharedRecorder 的代理方法,监听错误回调和状态改变:

// RPScreenRecorderDelegate methods
func screenRecorder(_ screenRecorder: RPScreenRecorder, 
  didStopRecordingWith previewViewController: RPPreviewViewController?,
  error: Error?) {
  guard error == nil else {
    print("There was an error recording: \(String(describing:
      error?.localizedDescription))")
    self.isRecording = false
    return
  }
}

func screenRecorderDidChangeAvailability(_ screenRecorder:  
  RPScreenRecorder) {
  recordButton.isEnabled = sharedRecorder.isAvailable
  if !recordButton.isEnabled {
    self.isRecording = false
  }
}
复制代码

使用方法不算太难,此处不再过多展开,详情可购买阅读正版书籍.

第四部分读书笔记结束!


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

刷屏

刷屏

[美] 凯文•阿洛卡 / 侯奕茜、何语涵 / 中信出版社 / 2018-10-1 / 68.00

1. YouTube流行趋势经理,解密如何打造爆款视频 在视频时代,制造互动,才能创造潮流 用户不再是被动的观众,而是主动的传播者 2. 《刷屏》以行内人视角解读: 病毒视频 粉丝经济 网红产业 平台如何为内容创作者赋能 3. 你是否常常被病毒视频刷屏?你是否觉得很多网红火爆到“无法用常理解释”? 视频时代已经到来,我们每天观看网络......一起来看看 《刷屏》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

在线进制转换器
在线进制转换器

各进制数互转换器

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具