0
雷鋒網(wǎng)按:本文為雷鋒字幕組編譯的技術博客,原標題 face-api.js?—?JavaScript API for Face Recognition in the Browser with tensorflow.js,作者為 Vincent Mühler 。
翻譯 | 王飛 趙朋飛 整理 | MY
我可以很激動地說,我們終于有可能在瀏覽器中運行人臉識別程序了!在這篇文章中,我會給大家介紹一個基于 TensorFlow.js 核心的 JavaScript 模塊,這個模塊叫做 face-api.js。為了實現(xiàn)人臉檢測、人臉識別以及人臉特征點檢測的目的,該模塊分別實現(xiàn)了三種類型的卷積神經(jīng)網(wǎng)絡。
和往常一樣,我們先看一個簡單一點的代碼實例,用幾行的代碼以便能夠讓大家可以直接開始使用這個包。我們開始吧!
第一個 face-recognition.js,那么現(xiàn)在還有其他包嗎?
如果你有閱讀過我的另外一篇關于 nodejs 進行人臉識別方面的文章:Node.js+face-recognition.js: Simple and Robust Face Recognition using Deep Learning , 你可能會意識到,一段時間以前,我構建過一個相似的包。比方說三個 face-recognition.js,將人臉識別功能引入 nodejs 當中。
起初,我沒有想到在 javascript 社區(qū)中對臉部識別軟件包的需求如此之高。對于很多人來說,face-recognition.js 似乎是一個很不錯的免費軟件包了,另外也有像微軟和亞馬遜提供的付費軟件包。但是,一直有人問我能否在瀏覽器中完整地運行整個人臉識別的流程
最后的答案是肯定的,多虧了 tensorflow.js,利用好 tfjs-core, 我成功實現(xiàn)了部分相似的工具,這些小工具能夠讓你得到和使用 face-recognition.js 幾乎相似的運行結(jié)果,并且是在瀏覽器中。而且最棒的一點是你不需要再安裝任何依賴項,它可以直接運行。額外的好處是它還支持 GPU 加速,在 WebGL 上運行操作。
這足讓我相信 JavaScript 社區(qū)需要這樣的瀏覽器軟件包!接下來就是發(fā)揮你自己的想象力,你可以用這個來構建各種各樣的應用程序。:)
如何用深度學習來解決人臉識別的問題
如果你是那種想要盡快開始的人(或妹子),你可以跳過這一部分并直接跳到代碼部分。但為了更好地理解 face-api.js 中用于實現(xiàn)人臉識別的方法,我強烈建議你按照步驟來,因為我經(jīng)常被問到這一部分的問題。
為了簡單起見,我們實際想要實現(xiàn)的是給定一個人的臉部圖像然后對他/她進行識別,給定的圖像即輸入圖像。我們解決這個問題的方法是為每個我們想要識別的人提供一個(或多個)圖像,并用人名稱標記,即參考數(shù)據(jù)?,F(xiàn)在我們將輸入圖像與參考數(shù)據(jù)進行比較,并找到最相似的參考圖像。如果兩個圖像足夠相似,那我們就輸出人名,否則我們輸出'未知'。
聽起來像是個不錯的計劃!但是這里仍存在兩個問題。首先,如果我們有一張顯示多個人的圖像,并且我們想要識別所有這些圖像,那該怎么辦呢?其次,我們還需要能夠獲得度量兩張人臉圖像的相似性的量,以便進行比較。
人臉檢測
第一個問題的答案是人臉檢測。簡單地說,我們首先找到輸入圖像中的所有的人臉。對于人臉檢測,face-api.js 實現(xiàn)了 SSD(Single Shot Multibox Detector),它基本上是一個基于 MobileNetV1 的 CNN,在網(wǎng)絡頂部疊加了一些額外的預測層。
這個網(wǎng)絡返回包圍每張臉的 bounding box,以及其對應的分數(shù),即每個 boundingbox 中包含人臉的概率。這里的分數(shù)用于過濾邊界框,因為圖像中可能根本不包含人臉。另外要注意的是,即使圖像中只有一個人,為了得到 boundingbox,也應該首先進行人臉檢測這一步驟。
人臉特征點檢測與人臉對齊
第一個問題解決了 但是,我想指出我們接下來要對齊邊界框,在將它們傳遞到面部識別網(wǎng)絡之前,為每個框提取以面部為中心的圖像,因為這樣可以使面部識別更準確!
針對這個目標。face-api.js 已經(jīng)實現(xiàn)了一個簡單的 CNN,這個網(wǎng)絡能夠返回給定人臉圖片的 68 個臉部特征點。
根據(jù)特征點的位置,boundingbox 可以被確定在臉部的中心。下面顯示的是人臉檢測的結(jié)果(左)以及人臉對齊后的結(jié)果(右)。
人臉識別
現(xiàn)在我們可以將提取和對齊的人臉圖像提供給人臉識別網(wǎng)絡,該網(wǎng)絡基于類似 ResNet-34 的體系結(jié)構,基本上與 dlib 中實現(xiàn)的體系結(jié)構相對應。該網(wǎng)絡已經(jīng)被訓練,能夠?qū)W習將人臉的特征映射到一個人臉描述器上(具有 128 個值的特征向量),這一過程通常也被稱為面部嵌入。
現(xiàn)在回到我們最開始比較兩張臉的這個問題上:我們將使用每個提取的面部圖像的面部描述符,并將它們與參考數(shù)據(jù)的面部描述符進行比較。更確切地說,我們可以計算兩個面部描述符之間的歐氏距離,并基于閾值判斷兩個面是否相似(對于 150×150 大小的面部圖像來說,0.6 是比較好的閾值)。使用歐幾里德距離的效果非常好,但當然你也可以使用你選擇的任何類型的分類器。以下 gif 可視化了兩張圖片通過歐幾里德距離進行比較的過程。
現(xiàn)在,讓我們消化一下人臉識別的理論,接下來用代碼來編寫一個例子吧。
編碼時間!
在這個簡短的例子中,我們將逐步了解如何在以下輸入圖像中識別多個人臉:
包含腳本
首先,從 dist/face-api.js 獲取最新的編譯,或者 從 dist/face-api.min.js 獲取修訂版,并將腳本包含進來:
如果使用 npm:
加載模型數(shù)據(jù)
根據(jù)您的應用程序的需求,您可以專門加載您需要的模型,但是要運行一個完整的端到端示例,我們需要加載人臉檢測、 臉部特征點和人臉識別模型。模型文件可以在 repo 或點擊這里獲取。
模型的權重已經(jīng)被量化,與原始模型相比,將模型文件的大小減少了 75%,以允許您的客戶只加載所需的最少數(shù)據(jù)。此外,模型權重被分割成最大 4 MB 的塊,允許瀏覽器緩沖這些文件,以便這些文件只被加載一次。
模型文件可以簡單的被當做瀏覽器的靜態(tài)資源,或者你可以在其他地方托管它們,并可以通過特定的路由或 URL 加載這些文件。假設你將它們和你的其他資源一起放到模型目錄下(public/models):
或者,如果你僅僅想加載特定的模型:
從輸入圖像中獲得對所有面孔的完整描述
神經(jīng)網(wǎng)絡接受 HTML 圖像、畫布、視頻或者張量等形式的輸入。使用 score > minScore 檢測面部邊界框,我們簡單的說:
完整的面部描述包括檢測結(jié)果(邊界框+分值),臉部特征,以及計算描述符。正如你所看到的,在前面的討論中 faceapi.allFaces 在后臺做了所有的工作。然而,你也可以手動獲取臉部位置和特征點。如果你以此為目標的話,可以在 github repo 找到很多例子。
注意,邊界框和特征點位置依賴于原始圖像/媒體的大小。如果顯示的圖像大小與原始圖像大小不一致,您可以簡單地調(diào)整大?。?/p>
我們可以通過將邊界框繪制到畫布上來可視化檢測結(jié)果 :
臉部特征點可以如下方式顯示:
通常,我所做的是將一個絕對定位的畫布疊加在 img 元素的頂部,它們的寬度和高度是相同的(可以查看 github 上的示例了解更多信息)
面部識別
現(xiàn)在我們知道了如何檢索輸入圖像中所有人臉的位置和描述了,我們將從一些圖像中指出每個人臉并計算出人臉的描述符。這些描述符將會是我們的參考數(shù)據(jù)。
假設我們有一些可用的示例圖像,我們首先從一個 url 獲取圖像,并使用 faceapi.bufferToImage 從數(shù)據(jù)緩沖區(qū)中創(chuàng)建 HTML 圖像元素:
接下來,對于每一個圖像,我們定位主題并計算面部描述符,就像我們之前對輸入圖像所做的操作:
現(xiàn)在,我們要做的所有事情都是循環(huán)遍歷我們輸入圖像的面部描述,并找到與參考數(shù)據(jù)距離最小的描述符:
正如前面提到的,我們使用歐氏距離度量相似度,結(jié)果證明它是有效的。我們最終得到了在輸入圖像中檢測到的每個面孔的最佳匹配。
最后,我們可以將邊界框和它們的標簽一起繪制到畫布上,以顯示結(jié)果:
好了!到目前為止,我希望您已經(jīng)了解了如何使用這個 api。另外,我還建議您看一下 repo 的其他例子?,F(xiàn)在盡情享受這個軟件包吧!
如果你喜歡這篇文章,歡迎點贊并在 medium 或 twitter 上關注我。也歡迎在 github repository 上評價。請繼續(xù)關注更多教程!
雷鋒網(wǎng)雷鋒網(wǎng)
雷峰網(wǎng)原創(chuàng)文章,未經(jīng)授權禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。