创建基于脸型的AR体验


翻译完了才发现已经有人翻译过了,而且还是自己收藏过的,服了自己了。
不过苹果的文档也有些许更新,也总算是过了一遍,大家随意看看,有示例代码运行效果截图,整体效果还是不错的。ps:iPhone X也是不错的😈。


原文 Creating Face-Based AR Experiences

使用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来创建你自己的渲染器(参考ARSKViewDisplaying 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)
}
IMG_5284.JPG

在用户的脸上放置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”被用户鼻子遮挡的效果。

IMG_5283.JPG

让一个复合形状的角色活起来

除了上述两个对于脸部网格的应用之外,ARKit还以blendShapes字典的方式提供一个更抽象的用户脸部表情模型。你可以使用这个字典给出的系数值来控制你自己的2D或者3D模型的动画参数,创建一个跟随用户实际脸部活动和表情的对象(比如一个狗狗头像)。

作为一个复合形状动画的基本范本,这个示例包含了一个简易的机器人形象🤖模型,这个模型是使用SceneKit原生形状创建的(参考源码中的robotHead.scn文件)。

要获取用户当前的面部表情,请查阅blendShapes字典,这个字典从代理回调renderer(_:didUpdate:for:)的面部锚点中取得:

func update(withFaceAnchor faceAnchor: ARFaceAnchor) {
    blendShapes = faceAnchor.blendShapes
}

然后,检查这个字典的键值对来计算你的模型的动画参数。总共有52个独立的ARFaceAnchor.BlendShapeLocation系数。你的app可以使用必要的参数来创建你脑海中的艺术化效果。在这个示例中,RobotHead类做了相关的计算,将eyeBlinkLefteyeBlinkRight映射到机器人眼睛一个轴的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
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容