ARKit

利用 ARKit 偵測與追蹤臉部動作 建立絢麗的使用者體驗

利用 ARKit 偵測與追蹤臉部動作 建立絢麗的使用者體驗
利用 ARKit 偵測與追蹤臉部動作 建立絢麗的使用者體驗
In: ARKit, iOS App 程式開發, Swift 程式語言

去年 Apple 推出的新功能中,其中一個最創新的功能就是原深感測鏡頭 (True Depth Camera)。原深感測鏡頭對軟硬體工程師來說,支援了 FaceID 這個安全的面部識別系統;而對於開發者,原深感測鏡頭就開創了許多可能性,尤其是在基於臉部互動 (face-base interactions) 這方面。

在開始這篇 ARKit 教學之前,讓我快速說明一下相機的不同部分。原深感測鏡頭和大部分的 iPhone/ iPad 的前置相機一樣,有內嵌麥克風、具七百萬像素的相機、環境光源偵測器 (ambient light sensor)、距離感應器 (proximity sensor)、與揚聲器。而原深感測鏡頭最獨特的地方,就是獨有的測繪點投射器 (dot projector)、泛光照射器 (flood illuminator)、與紅外線鏡頭 (infrared camera)。

測繪點投射器會投射超過 3 萬個隱形測繪點到使用者的臉上,以建構成一個面部測繪圖(文章後部會提到);而紅外線相機就會讀取測繪點,擷取成一張紅外線影像,並傳送資料到 Apple A12 Bionic 處理器作比對;最後,泛光照射器就會利用紅外線,方便在黑暗環境辨識容貌。

這些不同的感測元件整合在一起,就可以創造如 Animojis 和 Memojis 這種神奇體驗。有了原深感測鏡頭,我們就可以利用使用者臉部和頭部的 3D 模型,為 App 建立更多特殊效果。

教學範例專案

我相信對於開發者而言,最重要的就是學會使用原深感測鏡頭,應用臉部追蹤功能,為使用者建構令人驚艷的臉部辨識體驗。在本篇教學中,我將會說明如何利用 ARKit 框架中的 ARFaceTrackingConfiguration,去透過 3 萬個測繪點辨識不同的臉部動作。

最終成果會是這樣的:

true-depth-camera-demo

讓我們開始吧!

你需要在 iPhone X、XS、XR、或 iPad Pro(第三代)上執行這個專案,因為只有這些機型才支援原深感測鏡頭。文章中,我們會使用 Swift 5 和 Xcode 10.2。

編註:如果你對 ARKit 還不熟悉,可以參考我們另一篇 ARKit 教學

建立 ARKit 範例來追蹤臉部動作

首先,打開 Xcode 建立一個新 Xcode 專案。在 Templates 下,請確認選擇的是 iOS 的 Augmented Reality App。

接著,請為專案命名。我把專案命名為 True Depth。請確認你設定了 Language 為 Swift,Content Technology 為 SceneKit

arkit-face-tracking-1

前往 Main.storyboard, 這裡應該有一個 Single View,而當中的 ARSCNView 應該已經連接到程式碼上。

arkit-face-tracking-2

我們真正需要做的其實非常簡單!我們只需要加入一個 UIView,再在 View 內加入一個 UILabel。這個 Label 將會告知使用者,他們正在展示甚麼臉部表情。

UIView 拖拉至 ARSCNView 內,然後來設定條件。將 Width 設定為 240pt,Height 為 120pt,然後再設定 Left 與 Bottom 為 20pt。

arkit-face-tracking-3

為了美觀的設計,讓我們將 View 的 alpha 設為 0.8。現在,將 UILabel 拉到你剛完成的 view 內,再將所有的邊設為 8pt

arkit-face-tracking-4

最後,把 Label 對齊設置到中間。設置好後,你的 storyboard 應該會像這樣:

arkit-face-tracking-5

現在,讓我們來設定 IBOutletsViewController.swift 連接。轉換到 Assistant editor 模式,按住 Control 鍵點選 UIViewUILabel,然後將它們拉到 ViewController.swift 來建立 IBOutlets

arkit-face-tracking-6

你應該可以建構兩個 outlet:faceLabellabelView

arkit-face-tracking-7

建立臉部網格 (Face Mesh)

因為我們選擇了 Augmented Reality App 為程式碼範本,範本內有些不需要的程式碼,所以讓我們先把程式碼整理一下吧。將 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 scene;但我們並不需要這個 scene,所以我們刪除了它。然後,我們可以在 project navigator 內刪除 art.scnassets 資料夾。最後,我們增加兩段程式碼到 viewDidLoad 方法內:

  1. 首先,我們會把 labelView 的邊角設置為圓角。這其實只是一個設計偏好。
  2. 接著,我們需要確認機型是否支援 ARFaceTrackingConfiguration。這是我們用來建立臉部網格的 AR 追蹤功能,如果我們沒有確認的話,程式就會崩潰;而如果使用的機型不支援設定的話,就將會呈現錯誤訊息。

接著,我們將在 viewWillAppear 方法內改變一行程式碼:將常數 configuration 改為 ARFaceTrackingConfiguration()。如此一來,你的程式碼應該會像這樣:

face-mesh-1

然後,我們需要加入 ARSCNViewDelegate 方法。將下列程式碼加到 // MARK: - 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
}

這個程式碼將在 ARSCNView 呈現時執行。首先,我們建立 sceneView 的臉部圖形資訊,並將它設給一個常數 faceMesh。然後,我們將此圖形資訊指派給 SCNNode,並設置材料 (material) 為 node。對於 3D 物件而言,這個材料通常是 3D 物件的顏色或紋理 (texture)。

為了建構臉部網格,你可以使用兩種材料:填滿材料 (fill material) 或線材料 (lines material)。我比較傾向使用線材料,所以在程式碼中設定了 fillMode = .lines,但你可以自由選用。現在你的程式碼應該像是這樣:

face-mesh-2

如果你執行這個 App,你應該會看到這樣的畫面:

face-mesh-demo

更新臉部網格

你可能會注意到,臉部網格並沒有隨著你的表情變化(如眨眼、微笑、或打哈欠等)而更新。這是因為我們還需要在 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)
    }
}

每當 sceneView 更新,這段程式碼就會執行。首先,我們定義一個 faceAnchorsceneView 內臉部被偵測到的錨點 (anchor)。這個錨點是當執行臉部追蹤 AR session 時,被偵測臉部的姿態 、拓撲 (topology)、表情的資料。我們也定義一個叫 faceGeometry 的常數,這是為被偵測臉部的拓撲資料。利用這兩個常數,我們就可以每次都更新 faceGeometry

再次執行程式碼,現在每當你改變臉部表情時,臉部網格就會以 60 幀率 (fps) 更新。

face-mesh-update

分析臉部表情變化

首先,在檔案最頂部建立一個變數:

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 為一個函數。

  1. blendShapes 是一個命名系數的字典,根據特定臉部表情變化,表示檢測到的臉部表情。Apple 提供超過 50 種以上的系數,來偵測不同的臉部表情變化。以我們的需求而言,我們僅會使用 4 種:mouthSmileLeftmouthSmileRightcheekPuff、和 tongueOut
  2. 我們使用系數來確認臉部執行這些表情的概率。為了檢測微笑,我們加入嘴巴的右側和左側的概率。我發現,設定微笑的概率為 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
        }

    }
}

現在每當 sceneView 更新,就會執行 expression 方法。因為這個函數設定 analysis 字串,所以我們終於可以設定 faceLabel 的文本到 analysis 字串上。

我們完成所有的程式碼囉!執行程式碼,你應該會得到文章開頭的成果。

true-depth-camera-demo

總結

利用 ARKit 開發基於臉部的使用者體驗這個功能,背後還有很多可能性。遊戲和 App 可以將原深感測鏡頭用於各種用途。我最愛的其中一個 App 就是 Hawkeye Access,這是一個讓使用者可以用眼睛來控制的瀏覽器。

如果你想了解更多關於原深感測鏡頭的相關資訊,你可以看看 Apple 的官方影片 Face Tracking with ARKit。你也可以在 GitHub 上下載本次教學的專案。

譯者簡介:Oliver Chen-工程師,喜歡美麗的事物,所以也愛上 Apple,目前在 iOS 程式設計上仍是新手,正研讀 Swift 與 Sketch 中。生活另一個身份是兩個孩子的爸,喜歡和孩子一起玩樂高,幻想著某天自己開發的 App,可以讓孩子覺得老爸好棒!。聯絡方式:電郵 [email protected]

原文How to Detect and Track the User’s Face Using ARKit

作者
Sai Kambampati
Sai Kambampati 是程式開發員,生活於美國加州薩克拉門托,於2017獲得Apple's WWDC獎學金。精於 Swift及Python語言,渴望自家開發人工智能產品。閒時喜歡觀看Netflix、做健身或是遛漣圖書館中。請到推特追蹤 @Sai_K1065 。
評論
更多來自 AppCoda 中文版
透過 Reality Composer 和 RealityKit 輕鬆地創建 3D AR Apps
ARKit

透過 Reality Composer 和 RealityKit 輕鬆地創建 3D AR Apps

RealityKit 是 2019 年推出的新框架,用於實作高性能 3D 模擬和渲染功能,而 Reality Composer 就讓初學者無需編寫任何程式碼,都可以輕鬆地創建互動的 AR 體驗。在這篇文章中,你將學會使用這兩個框架,構建互動的 3D AR App。
很好! 你已成功註冊。
歡迎回來! 你已成功登入。
你已成功訂閱 AppCoda 中文版 電子報。
你的連結已失效。
成功! 請檢查你的電子郵件以獲取用於登入的連結。
好! 你的付費資料已更新。
你的付費方式並未更新。