苹果公司近几年推出的最具创新性的发明之一是True Depth camera。作为开发者,深度相机为我们打开了一个充满可能性的世界,特别是在人脸交互领域。
在我们开始这个ARKit教程之前,简单介绍一下相机的不同部分。与大多数iPhone/iPad前置摄像头一样,True Depth camera配有麦克风、700万像素摄像头、环境光传感器、近距离传感器和扬声器。True Depth camera本身是增加了一个点投影仪,泛光照明,和红外相机。
点投射器在你的脸上投射出超过30,000个不可见的点来构建一个本地地图(你将在本教程的后面看到这一点)。红外摄像机读取圆点图案,捕获红外图像,然后将数据发送到A12/A13仿生芯片,以确认匹配。最后,漫射照明装置允许不可见的红外线识别你的脸,即使是在天黑的时候。这些功能可以让我们一起创造了一些神奇的体验,如Animojis和Memojis,当然还有炫酷的AR效果。
以下内容由公众号:AIRX社区(国内领先的AI、AR、VR技术学习与交流平台) 整理
效果预览
Step 1:新建项目
打开Xcode,选择AR模版创建,Content Technology选择SceneKit
打开Main.storyboard
在视图中添加一个UIView和一个UILabel。告诉用户他们正在做的面部表情。将一个UIView拖放到ARSCNView中,设置约束条件:宽度为240pt,高度为120pt;将左侧和底部约束设置为20pt。
将视图的alpha值设置为0.8,并将UILabel拖放到刚刚添加的视图中,约束设置为8,如下图所示:
将刚刚创建的组件写入代码,命名为faceLabel 和 labelView
Step 2:创建Face Mesh
稍微整理一下代码。因为我们选择了AR作为模板,所以有些代码我们不需要。将viewDidLoad函数更改为:
override func viewDidLoad() {
super.viewDidLoad()
// 1
labelView.layer.cornerRadius = 10
sceneView.delegate = self
sceneView.showsStatistics = true
// 2
guard ARFaceTrackingConfiguration.isSupported else {
fatalError("Face tracking is not supported on this device")
}
}
本来这个模版代码是加载一个3D场景。然而,我们不需要这个场景,所以我们删除了它。然后删除art.scnassets文件夹。
然后向viewDidLoad方法添加了两段代码,这部分代码主要是检查设备是否支持ARFaceTrackingConfiguration。这是AR跟踪设置,因为我们需要使用它创建一个脸部网格。如果我们不检查设备是否支持这个,我们的应用程序将崩溃。
接下来,更改viewWillAppear函数中的一行。将常量配置更改为ARFaceTrackingConfiguration(),如下图所示:
添加ARSCNViewDelegate方法
func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
let faceMesh = ARSCNFaceGeometry(device: sceneView.device!)
let node = SCNNode(geometry: faceMesh)
node.geometry?.firstMaterial?.fillMode = .lines
return node
}
首先,创建了sceneView的face几何体,将其设置为常量faceMesh。然后,我们将这个几何图形分配给SCNNode。接着设置节点的材质。
对于face mesh,你可以使用两种材质——填充材质或线条材质。此次示例使用的是线条材质(fillMode = .lines),现在的代码应该是这样的:
现在运行程序,效果如下图:
Step 3:更新Face Mesh
运行后发现当你改变你的面部特征(眨眼、微笑、打哈欠等)时,mesh不会更新。这是因为我们需要在renderer(_nodeFor)方法下添加renderer(_didUpdate:):
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
if let faceAnchor = anchor as? ARFaceAnchor, let faceGeometry = node.geometry as? ARSCNFaceGeometry {
faceGeometry.update(from: faceAnchor.geometry)
}
}
将faceAnchor定义为它在sceneView中检测到的面。achor是人脸跟踪AR session中检测到的人脸姿态、拓扑结构和表情信息。我们还定义了常数面几何,这是一个拓扑的脸检测。使用这两个常量,我们每次都会更新faceGeometry。
再次运行代码。你会看到mesh随着你的面部特征改变而更新
Step 4:表情特征
在文件的顶部创建一个变量
var analysis = ""
在文件末尾创建以下函数:
func expression(anchor: ARFaceAnchor) {
// 1
let smileLeft = anchor.blendShapes[.mouthSmileLeft]
let smileRight = anchor.blendShapes[.mouthSmileRight]
let cheekPuff = anchor.blendShapes[.cheekPuff]
let tongue = anchor.blendShapes[.tongueOut]
self.analysis = ""
// 2
if ((smileLeft?.decimalValue ?? 0.0) + (smileRight?.decimalValue ?? 0.0)) > 0.9 {
self.analysis += "You are smiling. "
}
if cheekPuff?.decimalValue ?? 0.0 > 0.1 {
self.analysis += "Your cheeks are puffed. "
}
if tongue?.decimalValue ?? 0.0 > 0.1 {
self.analysis += "Don't stick your tongue out! "
}
}
上面的函数以ARFaceAnchor作为参数。
blendShapes是一个根据特定面部特征的移动表示检测到的面部表情的字典。Apple提供了50多个系数来检测各种不同的面部特征。上面我们只使用了4种:mouthSmileLeft、mouthSmileRight、cheekPuff和tongueOut。
为了检测一个微笑,我们将嘴的左右两边的概率相加。发现0.9的微笑和0.1的脸颊和舌头效果最好。
将可能获取到的值添加到analysis字符串,然后更新renderer(_didUpdate:)方法:
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
if let faceAnchor = anchor as? ARFaceAnchor, let faceGeometry = node.geometry as? ARSCNFaceGeometry {
faceGeometry.update(from: faceAnchor.geometry)
expression(anchor: faceAnchor)
DispatchQueue.main.async {
self.faceLabel.text = self.analysis
}
}
}
运行测试
完整项目代码:
https://github.com/appcoda/Face-Mesh
参考文章:
https://www.appcoda.com/arkit-face-tracking/
ARKit与iPhone的True Depth camera的结合会有很多酷炫的、创新的、脑洞大开的应用场景,大家有什么好的idea可以在下面留言哦!!!
可以关注下公众号(AIRX社区),一个专注AI、AR、VR学习与交流的平台。