ARKit從入門到精通(5)--AR人臉識別應用

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章