蘋果Core ML和Vision入門-「刷臉」與面部識別功能
備註:本文編譯自iOS 11 by系列教程(http://raywenderlich.com)
前言
在剛剛過去的蘋果十周年iPhone發布會上,除了Steve Jobs Theatre,可能大家印象最深刻的就是iPhone X的面部識別(face id)功能了。關於face id,網上已經有了無數條關於用「刷臉」來買買買的段子。
當然,要實現這種神奇的「刷臉」功能,除了iphone x「留海「部分的多個攝像頭和感測器之外,相關的軟體演算法也是必不可少的。
在本教程中,我們將了解蘋果iOS11中除了ARKit之外的極具前瞻性的框架,也即Core ML和Vision框架,並通過一個示例來講解如何利用Core ML和Vision框架來實現人臉識別。
需要提醒大家的是,iPhone X的強大「刷臉」功能是軟硬體完美結合的表現,這也是蘋果一貫的風格。我們使用Core ML和Vision可能沒法實現那種魔術般的效果,但也是非常值得去探索的。
人類都是視覺動物。根據Time雜誌的統計,2016年的Top10非遊戲類應用中,有7個跟圖片和/或視頻分享有關(美國排行榜)。其中的一些應用,諸如Facebook,Snapchat和Instagram等,給用戶提供了豐富多彩的圖像相關功能,比如圖像校正、添加濾鏡、面部識別等等。
在iOS11中的全新Vision框架基於Core Image和Core ML框架構建,並且提供了幾個簡單易用的功能,用於分析圖片和視頻。它具體支持的特性包括面部跟蹤,面部識別,面部特徵點,文本檢測,矩陣檢測,二維碼檢測,物體跟蹤,以及圖像登記等。
在本章的內容中,我們將學習如何檢測人體面部,學習面部特徵點,以及如何使用Vision和Core ML來給場景分類。
開始前的準備
在開始學習之前,請確保已經安裝了Xcode9的正式版(9月13日已從beta版升級為正式版,同時開發者版本的iOS也已經推送了GM版)。
使用Xcode打開本章的起始項目:GetReady。
項目地址:鏈接:http://pan.baidu.com/s/1bpD7DAv 密碼:35fb
這個項目的作用是查看你的照片,然後為不同的場景對家人和朋友做一些裝飾。這些場景包括徒步旅行,以及去海灘度假。對於徒步旅行的場景,我們可以給家人和朋友戴上遊客的帽子,而對於海灘曬日光浴的場景則戴上太陽鏡。
關於圖片細節的視圖控制器ImageViewController.swift這個文件將是本教程的學習重點。
編譯運行應用,此時我們會看到一個空白的屏幕。點擊右上角的「+」按鈕可以打開照片選擇器。
注意:如果在打開照片選擇器的時候看到console裡面出現一些警告或log信息,大可以忽略。
如果你使用的是iOS模擬器,那麼會預載入一些漂亮的花朵和瀑布。但是因為本教程主要涉及人臉,因此這些用處不大。不過好在iOS 11模擬器允許我們添加圖片!
我們可以用自己的照片,或者直接從GetReadyimages文件夾中找到hiker.jpg文件,然後將其拖到Photos應用中。這樣它就被導入到Simulator中,從而在應用中可用。
注意看這裡的「留海」造型,因為我在模擬器裡面選的是iPhone X~
而且這個模擬器裡面是沒有Home鍵的,那麼想返回到Simulator主界面怎麼辦呢?只需要從最下方往上拖動,就可以回到桌面了。想來這也是iPhone X設備上的正式操作吧,有點小期待。
好了,現在返回這個應用,點擊右上角的加號,選擇剛才的新照片。此時這個照片將以縮略圖的形式顯示在屏幕上。
點擊(模擬器)縮略圖,圖片將會放大顯示,而這裡也將是對圖片作出修飾的視圖控制器。
照片裡面的哥們看起來很享受這個徒步之旅,但是好像漏掉了一些什麼。是的,他sans chapeau(法語-沒有帽子)!讓我們給這哥們送一頂帽子,來保護他此刻光芒萬丈的禿頭!
面部檢測
為了找到添加帽子的合適位置,我們需要找到照片中每個頭部的尺寸。幸運的是,Vision很擅長的一件事情就是識別面部的基本輪廓。
注意:Core Image中的CIDector同樣可以用於識別照片中的人臉。不過新的Vision提供了更為強大的面部識別功能,而且可以識別相對更小的面部,側臉,被物體、帽子和眼鏡擋住的臉。當然,不太好的地方就是Vision的速度相對較慢,而且需要更強大的計算性能,也更耗電?
對於本教程的第一部分,我們的目標是給照片中所識別出的每個人體頭部繪製一個遊客帽子。而在後續的內容中,我們將基於更多的數據信息來調整帽子的朝向,同時給海灘上享受日光浴的人們戴上太陽鏡。
面部輪廓檢測
在Xcode中打開ImageViewControlller.swift,替代其中的viewWillAppear(_:)方法如下:
以上代碼完成了對Vision API的調用:
1.Vision不適用於UIImage,而是對圖片的原始數據,像素緩存,CIImage或CGImage有效。
2.設置了orientation屬性,從而確保所檢測的輪廓與圖片是同一方向的。
3.這行代碼創建了一個面部檢測請求。這裡的completion handler是一個類實例方法,很快我們將實現它。
4.我們需要一個圖片請求的handler來處理單一圖片的一個或多個請求。
5.Vision請求可能或耗費一些時間,因此最好是在背景隊列中執行。
6.perform(-:)獲取了請求列表,並執行面部檢測的任務。在檢測過程的最後,將從背景隊列中觸發請求調用。
Completion handler
正如其名字所表示的,VNDectectFaceRectangleRequest用於發現圖片中的面部輪廓。Vision請求將調用所檢測物體數組的completion handler。
找到handleFaces(request:error:)方法,並使用以下代碼替換:
以上代碼完成了以下任務:
1.確認請求返回了有效的VNFaceObservation元素的results數組。
2.將真正困難的工作交給main隊列中的另一個函數。
當然這個函數目前還沒有定義,因此Xcode肯定會提示出錯的。為了解決該問題,我們需要在剛才的handleFaces():方法之後添加一個新的observation-handling方法:
以上方法遍歷了所有的observations,並從進行面部檢測的圖片中變換坐標和定義區域。
1.這裡我們確定了image view視圖中圖片的真實邊界。因為image view的內容填充模式是Aspect Fit,因此會自動縮放以滿足image view的至少一個維度大小。也就是說另外一個維度就無法與image view的坐標對齊。如果選擇另一種模式,比如Scale to Fill,可以簡化這個計算過程,但是看起來效果就不太好了。
2.對每個observation,我們都需要將其坐標轉換到imageView的坐標。
3.我們將面部輪廓封裝到一個定製的FaceDimensions結構中,並將其添加到一個數組中。該結構的作用是在應用中傳遞面部數據。
4.最後,我們需要將所有的面部數據添加到annotationView之中,後面將用它在原始圖片上繪製自定義的圖片。
之所以需要第二步,是因為observation的boundingBox是在Core Graphics的坐標系中正交化的,其原點位置在左下角。當我們需要在某個視圖上開始繪製之前,需要對bounding box做以下操作:
1.進行denormalize操作,使其符合輸入的圖片大小。
2.將其移入UIKit的坐標系
3.將其縮放到繪製的長寬比
4.將其轉換到圖片在image view中的位置。
在繼續學習之前,我們先讓以上代碼可以正常運行。
打開annotationView.swift,然後更改drawDebug變數的值為true,具體如下:
這樣一來,就將在所識別的臉部繪製綠色的方框。
編譯運行程序,然後選擇一個照片,很快我們就會在所有識別出的面部看到一個綠色的方框。
當然,我承認這裡用iOS11 Simulator主要是想體驗下iPhone X的操作。那麼在我的iphone 6s Plus上是否可以正常運行呢?
我找了兩張昨天發布會上的照片,發現識別速度還是可以的,不過遺憾的是Tim Cook在幫主光芒萬丈之下沒被認出來,當然,這個我這個照片中Cook本身很模糊也有關係。
所以說,Core ML和Vision框架的強大威力還是值得信賴的。
敬請期待下一部分內容,我們將給識別出來的人臉加上一些裝飾品~
推薦閱讀: