JavaScript教程:為Web應(yīng)用程序添加人臉檢測功能
譯文【51CTO.com快譯】上周我們使用annyang為地圖界面增添了語音命令(https://www.infoworld.com/article/3400658/javascript-tutorial-add-speech-recognition-to-your-web-app.html)。本周我們將使用pico.js添加簡單的頭部跟蹤功能,進(jìn)一步增強我們的多模式界面。pico.js是一個精簡的JavaScript庫,與其說是生產(chǎn)級庫不如說是概念證明,但它在我研究過的人臉檢測庫中似乎效果***。
本文旨在用簡單的紅點開始顯示覆蓋在地圖上的用戶頭部位置:
圖1
我們先創(chuàng)建一個包裝pico.js功能的簡單React類,我們可以使用該功能來獲取用戶人臉的位置更新:
- <ReactPico onFaceFound={(face) => {this.setState({face})}} />
然后,如果檢測到人臉,我們可以使用該人臉位置的細(xì)節(jié)來渲染組件:
- {face && <FaceIndicator x={face.totalX} y={face.totalY} />}
我們在pico.js方面遇到的***個挑戰(zhàn)是,它用JavaScript實現(xiàn)了研究項目,未必是遵循現(xiàn)代JavaScript標(biāo)準(zhǔn)的生產(chǎn)級庫。除此之外,這意味著你無法執(zhí)行yarn add picojs命令。雖然pico.js入門(https://tehnokv.com/posts/picojs-intro/)深入淺出地介紹了對象檢測,但它更像是一篇研究論文,而不像API文檔。不過,所附的例子足以實際使用代碼。我花了幾小時將所附的樣本放入到一個比較簡單的React類中,我們可以用這個類充分利用代碼。
pico.js要做的***件事是加載級聯(lián)模型,這需要進(jìn)行AJAX調(diào)用,獲取對人臉預(yù)訓(xùn)練的模型的二進(jìn)制表示。(你可以使用同一個庫來跟蹤其他類型的對象,但需要使用官方的pico實現(xiàn)來訓(xùn)練自定義模型。)我們可以將該模型加載代碼放入到componentDidMount生命周期方法中。為了清楚起見,我進(jìn)一步將示例代碼抽象成另一個名為loadFaceFinder的方法:
- componentDidMount() {
- this.loadFaceFinder();
- }
- loadFaceFinder() {
- const cascadeurl = 'https://raw.githubusercontent.com/nenadmarkus/pico/c2e81f9d23cc11d1a612fd21e4f9de0921a5d0d9/rnt/cascades/facefinder';
- fetch(cascadeurl).then((response) => {
- response.arrayBuffer().then((buffer) => {
- var bytes = new Int8Array(buffer);
- this.setState({
- faceFinder: pico.unpack_cascade(bytes)
- });
- new camvas(this.canvasRef.current.getContext('2d'), this.processVideo);
- });
- });
- }
除了獲取和解析人臉檢測模型的二進(jìn)制表示并設(shè)置狀態(tài)外,我們還創(chuàng)建了一個新的camvas,它引用<canvas>上下文和回調(diào)處理程序。camvas庫將視頻從用戶的網(wǎng)絡(luò)攝像頭加載到canvas上,并為渲染的每個幀調(diào)用處理程序。loadFaceFinder的內(nèi)容幾乎就是pico.js提供的參考項目的相同副本。我們更改了存儲模型的位置,以便可以在狀態(tài)下訪問。我們通過react Ref來引用canvas上下文,而不是使用瀏覽器提供的DOM API。
我們的this.processVideo也幾乎與參考項目中提供的代碼相同。我們只需要做幾處更改。我們只想在加載模型時執(zhí)行代碼,于是對代碼的整個主體添加了檢查機制。我還使用我們預(yù)計用戶傳入的回調(diào)處理程序創(chuàng)建了這個React類,那樣我們只在定義該處理程序后運行處理代碼:
- processVideo = (video, dt) => {
- if(this.state.faceFinder && this.props.onFaceFound) {
- /* all the code */
- }
- }
我所做的唯一其他更改就是發(fā)現(xiàn)人臉后我們執(zhí)行的操作。pico.js示例在canvas上畫了幾個圓圈,但我們希望改而將數(shù)據(jù)傳回到那個回調(diào)處理程序。不妨稍微修改一下代碼,以便回調(diào)處理程序更容易處理這些值:
- this.props.onFaceFound({
- x: 640 - dets[i][1],
- y: dets[i][0],
- radius: dets[i][2],
- xRatio: (640 - dets[i][1]) / 640,
- yRatio: dets[i][0] / 480,
- totalX: (640 - dets[i][1]) / 640 * window.innerWidth,
- totalY: dets[i][0] / 480 * window.innerHeight,
- });
此格式讓我們可以傳回捕獲的canvas元素中人臉的絕對位置和半徑、canvas元素中人臉的相對位置以及canvas元素中的人臉位置。我們的定制課程基本完成。我還需要對pico.js和pico版本的camvas.js進(jìn)行幾處小的更改才能使用現(xiàn)代語法,但這些更側(cè)重關(guān)鍵字而不是邏輯。
現(xiàn)在我們可以將自定義ReactPico類導(dǎo)入到我們的App中,渲染它,如果檢測到人臉就有條件地渲染FaceIndicator類。我使用另外一些人臉檢測庫后驚訝地發(fā)現(xiàn),pico.js的準(zhǔn)確性和易用性很強,盡管它不是功能完備的庫。
原文標(biāo)題:JavaScript tutorial: Add face detection to your web app,作者:Jonathan Freeman
【51CTO譯稿,合作站點轉(zhuǎn)載請注明原文譯者和出處為51CTO.com】