蘋果公司近幾年推出的最具創新性的發明之一是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學習與交流的平臺。