翻譯完了才發現已經有人翻譯過了,而且還是自己收藏過的,服了自己了。
不過蘋果的文檔也有些許更新,也總算是過了一遍,大家隨意看看,有示例代碼運行效果截圖,整體效果還是不錯的。ps:iPhone X也是不錯的??。
使用iPhone X上的TrueDepth相機來根據用戶臉型放置3D內容,并根據用戶表情做動畫。
下載官網demo
SDKs
iOS 11.0+
Xcode 9.1+
概述
這個示例app展示了一個簡單的界面,讓你可以在擁有TrueDepth 前置相機的設備(iPhone X)上選擇4種AR特效。
- 只有相機拍攝的視圖,沒有AR特效。
- ARKit 提供的臉部網格(mesh),并提供自動的現實世界光線感知環境。
- 貼在用戶臉上的虛擬3D內容。
- 一個簡單的機器人形象,面部表情會跟用戶一致。
用示例app中的"+"按鈕來選擇不同的效果,如下圖所示。
使用SceneKit視圖來新建一個臉部追蹤Session
跟其他ARKit的應用一樣,臉部追蹤需要配置并運行一個session(一個ARSession對象),并在同一個視圖里同時渲染相機圖像和虛擬內容。如需更多關于session和view的詳細教程,參考 About Augmented Reality and ARKit 和Building Your First AR Experience。這個示例使用SceneKit來顯示AR體驗,你也可以用SpriteKit 或者用Metal來創建你自己的渲染器(參考ARSKView和Displaying an AR Experience with Metal)。
臉部追蹤跟其他ARKit的應用的不同之處在于配置session的所使用的類不同。要使用臉部追蹤,你得創建一個ARFaceTrackingConfiguration的實例,配置一下它的屬性,然后傳給view的AR session的run(_:options:)
方法,如下:
// 判斷是否支持FaceTracking
guard ARFaceTrackingConfiguration.isSupported else { return }
// 創建配置類
let configuration = ARFaceTrackingConfiguration()
configuration.isLightEstimationEnabled = true
// run
session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
追蹤臉部的位置和旋轉
當臉部追蹤激活的時候,ARKit自動向正在運行的AR session中添加ARFaceAnchor
對象,此對象包含用戶臉部的位置和旋轉信息。
提示
ARKit 只能檢測和提供以為用戶的臉部。如果攝像頭捕捉到多個臉,ARKit會挑選最大或者最能清晰分辨的臉部來識別。
在使用基于SceneKit的AR體驗時,你可以在renderer(_:didAdd:for:)
方法(遵循ARSCNViewDelegate協議)添加一個可以響應臉部錨點的3D物件。ARKit會在錨點上添加一個SceneKit節點(node),并在每一幀更新node的位置和旋轉屬性,因此你添加在這個節點上的任意SceneKit內容都會自動跟隨用戶臉部的位置和旋轉運動。
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
// Hold onto the `faceNode` so that the session does not need to be restarted when switching masks.
// 持有`faceNode`可以在換面具時不需要重啟session
faceNode = node
serialQueue.async {
self.setupFaceNodeContent()
}
}
在這個示例中,renderer(_:didAdd:for:)
方法調用了setupFaceNodeContent
方法來向faceNode
添加SceneKit內容。舉個??,如果你要改變demo中的showsCoordinateOrigin
變量,demo app就會在這個節點(faceNode?)上添加一個虛擬x/y/z軸,指示臉部錨點的原點和坐標系。
使用臉部幾何來給用戶臉部建模
ARKit提供了契合用戶臉部尺寸、形狀、拓撲結構(面貌結構)和當前面部表情的粗略3D網格(學過ABAQUS的可能比較容易理解)。ARKit中提供ARSCNFaceGeometry類,能讓你輕易在SceneKit中把網格可視化。
你的AR體驗可以使用這個網格來放置或者渲染一些看上去貼在臉上的內容。比如你可以通過在這個幾何網格上添加一些半透明的紋理來在用戶皮膚上畫一個虛擬紋身或模擬化妝。
要創建一個SceneKit臉部幾何對象,用你SceneKit視圖使用的Metal device來初始化一個ARSCNFaceGeometry變量:
// This relies on the earlier check of `ARFaceTrackingConfiguration.isSupported`.
// 要前置判斷是否支持ARFaceTrackingConfiguration
let device = sceneView.device!
let maskGeometry = ARSCNFaceGeometry(device: device)!
這段示例代碼的setupFaceNodeContent
方法(上文提到過)向scene添加了一個包含臉部幾何的node。通過使這個node成為臉部錨點的子node,臉部模型會自動追蹤用戶臉部的位置和旋轉。
要在用戶眨眼、說話或做不同的表情時讓模型隨用戶臉型變化,你需要在renderer(_:didUpdate:for:)
代理回調方法中取出更新的臉部網格。
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard let faceAnchor = anchor as? ARFaceAnchor else { return }
virtualFaceNode?.update(withFaceAnchor: faceAnchor)
}
然后在你需要匹配的scene中通過將新臉部網格傳入update(from:)
方法來更新ARSCNFaceGeometry對象:
func update(withFaceAnchor anchor: ARFaceAnchor) {
let faceGeometry = geometry as! ARSCNFaceGeometry
faceGeometry.update(from: anchor.geometry)
}
在用戶的臉上放置3D內容
ARKit提供的另一個臉部網格的應用是:在你的scene中創建一個遮擋幾何體。遮擋幾何體是指一個不渲染任何可見內容,允許相機圖像(實際物體)穿越展示,但可以遮擋scene中其他的虛擬內容的3D模型。
這項技術實現了虛擬物體與真實面部相互作用的假象,即使臉是2D的相機圖像而虛擬內容是個3D的渲染物體。舉個栗子,如果你放置一個遮擋幾何體和一個虛擬眼鏡在用戶臉上,臉部可以擋住鏡框。
要在臉上創建一個遮擋幾何體,首先要創建一個ARSCNFaceGeometry對象geometry
,就像上一個例子一樣。不同之處是上一個例子是用一個可見物體配置SceneKit的材質,這次要將材質設置為在渲染時使用深度而非顏色來渲染:
geometry.firstMaterial!.colorBufferWriteMask = []
occlusionNode = SCNNode(geometry: geometry)
occlusionNode.renderingOrder = -1
由于材料渲染的是深度,SceneKit渲染的其他物體會正確的顯示在它的前面或者后面。但因為材料并不渲染顏色,相機圖像會在它所在的位置出現。示例app用一個在用戶眼前的SceneKit物體(一個超大的AR文字),結合這個技術創建了一個逼真的“AR”被用戶鼻子遮擋的效果。
讓一個復合形狀的角色活起來
除了上述兩個對于臉部網格的應用之外,ARKit還以blendShapes字典的方式提供一個更抽象的用戶臉部表情模型。你可以使用這個字典給出的系數值來控制你自己的2D或者3D模型的動畫參數,創建一個跟隨用戶實際臉部活動和表情的對象(比如一個狗狗頭像)。
作為一個復合形狀動畫的基本范本,這個示例包含了一個簡易的機器人形象??模型,這個模型是使用SceneKit原生形狀創建的(參考源碼中的robotHead.scn文件)。
要獲取用戶當前的面部表情,請查閱blendShapes字典,這個字典從代理回調renderer(_:didUpdate:for:)
的面部錨點中取得:
func update(withFaceAnchor faceAnchor: ARFaceAnchor) {
blendShapes = faceAnchor.blendShapes
}
然后,檢查這個字典的鍵值對來計算你的模型的動畫參數。總共有52個獨立的ARFaceAnchor.BlendShapeLocation系數。你的app可以使用必要的參數來創建你腦海中的藝術化效果。在這個示例中,RobotHead
類做了相關的計算,將eyeBlinkLeft和eyeBlinkRight映射到機器人眼睛一個軸的scale值;把jawOpen映射到機器人的下巴位置的偏移距離。
var blendShapes: [ARFaceAnchor.BlendShapeLocation: Any] = [:] {
didSet {
guard let eyeBlinkLeft = blendShapes[.eyeBlinkLeft] as? Float,
let eyeBlinkRight = blendShapes[.eyeBlinkRight] as? Float,
let jawOpen = blendShapes[.jawOpen] as? Float
else { return }
eyeLeftNode.scale.z = 1 - eyeBlinkLeft
eyeRightNode.scale.z = 1 - eyeBlinkRight
jawNode.position.y = originalJawY - jawHeight * jawOpen
}
}