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