【知識普及】前端人臉檢測指南,快來看看
Shape Detection API 的發布已經有一些時日,其主要的提供的能力是給予前端直接可用的特征檢測的接口(包括條形碼、人臉、文本檢測)。本文將簡單的對其進行介紹,對前端進行人臉檢測進行普適性的講解。(本文不講算法~望輕拍)
1 背景與場景
人臉檢測(Face Detection)算是老生常談的課題了,在諸多行業應用廣泛,例如金融、安防、電子商務、智能手機、娛樂圖片等行業。其中涉及的技術也在不斷的演變,下面簡要介紹幾種思路:
a. 基于特征的人臉檢測
例如opencv中內置了基于Viola-Jones目標檢測框架的Harr分類器(實際上大多數分類器都是基于學習得到的),只需要載入對應的配置文件(haarcascade_frontalface_alt.xml)就能直接調用detectObject去完成檢測過程,同時也支持其他特征的檢測(如鼻子、嘴巴等)。
b. 基于學習的人臉檢測,其實也是需要通過算子提取的圖像中的局部特征,通過對其進行分類、統計、回歸等方式得到的具備更精確和快響應的分類器。
2 套路集錦
2.1 后端處理
前端通過網絡將資源傳輸到后端,后端統一處理需要檢測的圖像或視頻流,對后端的架構有一定的挑戰,同時網絡的延時往往不能給用戶帶來實時的交互效果。
2.2 客戶端處理
得益于OpenCV在跨語言和跨平臺的優勢,客戶端也能以較低的開發成本的提供人臉檢測的能力,并且可以通過JsBridge等方式向web容器提供服務,然而一旦脫離這個容器,孤立的頁面將失去這種能力。直到有一天……
2.3 開放服務
不知道從啥時候開始,云計算等概念拔地而起,計算的成本日益降低。各大研發團隊(如阿里云、Face++)都蠢蠢欲動又不緊不慢的上架了人臉檢測服務,甚至還帶上了各種特!殊!服!務!,人臉識別、活體識別、證件OCR及人臉對比等等等。
盡管不僅提供了客戶端的SDK以及前后端的API,但是,怎么說也要講講我純前端的方案吧。
3 時代帶來了什么
好吧,人臉識別在前端依然是在刀耕火種的遠古時代,然而,我們的基礎建設已經起步,希望后續的一些相關介紹能為各位看官帶來一定的啟發。
3.1 Shape Detection API
隨著客戶端硬件的計算能力逐漸提高,瀏覽器層面得到的權限也越來越多,由于圖像處理需要耗費大量的計算資源,實際上瀏覽器上也能承擔圖像檢測的一些工作,因此就搞出了個Shape Detection API。
以下幾個簡單的例子介紹了基本的用法,在嘗試編輯并運行這些代碼之前,請確保在你的Chrome版本以及該新特性已經被激活,另外該API受同源策略所限制:
chrome://flags/#enable-experimental-web-platform-features
條形碼檢測:Barcode Detection (For Chrome 56+)
- var barcodeDetector = new BarcodeDetector();
- barcodeDetector.detect(image)
- .then(barcodes => {
- barcodes.forEach(barcode => console.log(barcodes.rawValue))
- })
- .catch(err => console.error(err));
人臉檢測:Face Detection (For Chrome 56+)
- var faceDetector = new FaceDetector();
- faceDetector.detect(image)
- .then(faces => faces.forEach(face => console.log(face)))
- .catch(err => console.error(err));
文本檢測:Text Detection (For Chrome 58+)
- var textDetector = new TextDetector();
- textDetector.detect(image)
- .then(boundingBoxes => {
- for(let box of boundingBoxes) {
- speechSynthesis.speak(new SpeechSynthesisUtterance(box.rawValue));
- }
- })
- .catch(err => console.error(err));
3.2 圖像中的人臉檢測
圖像的人臉檢測比較簡單,只需要傳入一個圖片的元素,就能直接調起該API進行人臉識別了。然后接住canvas我們可以將檢測的結果展示出來。
核心代碼:
- var image = document.querySelector('#image');
- var canvas = document.querySelector('#canvas');
- var ctx = canvas.getContext("2d");
- var scale = 1;
- image.onload = function () {
- ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
- scale = canvas.width / image.width;
- };
- function detect() {
- if (window.FaceDetector == undefined) {
- console.error('Face Detection not supported');
- return;
- }
- var faceDetector = new FaceDetector();
- console.time('detect');
- return faceDetector.detect(image)
- .then(faces => {
- console.log(faces) // Draw the faces on the <canvas>.
- var ctx = canvas.getContext("2d");
- ctx.lineWidth = 2;
- ctx.strokeStyle = "red";
- for (var i = 0; i < faces.length; i++) {
- var item = faces[i].boundingBox;
- ctx.rect(Math.floor(item.x * scale), Math.floor(item.y * scale), Math.floor(item.width * scale), Math.floor(item.height * scale));
- ctx.stroke();
- }
- console.timeEnd('detect');
- })
- .catch((e) => console.error("Boo, Face Detection failed: " + e));
- }
處理效果:
3.3 視頻中的人臉檢測
視頻中的人臉檢測跟圖像相差不大,通過 getUserMedia 可以打開攝像頭獲取視頻/麥克風的信息,通過將視頻幀進行檢測和展示,即可實現視頻中的人臉檢測。
核心代碼如下:
- navigator.mediaDevices.getUserMedia({
- video: true, // audio: true
- })
- .then(function (mediaStream) {
- video.src = window.URL.createObjectURL(mediaStream);
- video.onloadedmetadata = function (e) {
- // Do something with the video here.
- };
- })
- .catch(function (error) {
- console.log(error.name);
- });
- setInterval(function () {
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- ctx.drawImage(video, 0, 0);
- image.src = canvas.toDataURL('image/png');
- image.onload = function() {
- detect();
- }
- }, 60);
處理效果:
3.4 時光倒流到沒有API的日子
實際上,在很久很久以前,也有不少解決方案存在。由于硬件條件以及沒有硬件加速等限制的情況,一直沒有被廣泛地投入生產。
a. tracking.js
tracking.js 是一款js封裝的圖像處理的庫,為瀏覽器帶來豐富的計算視覺相關的算法和技術,通過它可以實現顏色追蹤、人臉檢測等功能,具體特性如下:
b. jquery.facedetection
jquery.facedetection 是一款jquery / zepto 人臉檢測插件,基于跨終端能力超強的ccv中的圖像分類器和檢測器。
3.5 Node.js & OpenCV
node-opencv 模塊已經發布了有些年頭,盡管目前還不能***兼容v3.x,提供的API也比較有限,但能***兼容opencv v2.4.x。N-API的到來可能會帶來更多的驚喜。
設想一下在一個Electron或者Node-Webkit容器中,我們是否可以通過本地開啟websocket服務來實現實時的人臉檢測呢?實現的思路代碼如下:
后端處理邏輯:
- import cv from 'opencv';
- const detectConfigFile = './node_modules/opencv/data/haarcascade_frontalface_alt2.xml';
- // camera properties
- const camWidth = 320;
- const camHeight = 240;
- const camFps = 10;
- const camInterval = 1000 / camFps;
- // face detection properties
- const rectColor = [0, 255, 0];
- const rectThickness = 2;
- // initialize cameraconst camera = new cv.VideoCapture(0);
- camera.setWidth(camWidth);
- camera.setHeight(camHeight);
- const frameHandler = (err, im) => {
- return new Promise((resolve, reject) => {
- if (err) {
- return reject(err);
- }
- im.detectObject(detectConfigFile, {}, (error, faces) => {
- if (error) {
- return reject(error);
- }
- let face;
- for (let i = 0; i < faces.length; i++) {
- face = faces[i];
- im.rectangle([face.x, face.y], [face.width, face.height], rectColor, rectThickness);
- }
- return resolve(im);
- });
- });
- };
- module.exports = function (socket) {
- const frameSocketHanlder = (err, im) => {
- return frameHandler(err, im)
- .then((img) => {
- socket.emit('frame', {
- buffer: img.toBuffer(),
- });
- });
- };
- const handler = () => {
- camera.read(frameSocketHanlder);
- };
- setInterval(handler, camInterval);
- };
前端調用接口:
- socket.on('frame', function (data) {
- var unit8Arr = new Uint8Array(data.buffer);
- var str = String.fromCharCode.apply(null, unit8Arr);
- var base64String = btoa(str);
- img.onload = function () {
- ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
- }
- img.src = 'data:image/png;base64,' + base64String;
- });
4.1 未來的發展
這些前沿的技術將會在前端得到更為廣泛的應用和支持是毋庸置疑的,未來的圖像在前端也會隨著傳統圖像處理->學習+圖像處理的方式前進,這一切的功勞離不開基礎設施(硬件、瀏覽器、工具、庫等)的逐漸增強和完善,其中包括但不僅限于:
- getUserMedia/Canvas => 圖像 / 視頻的操作
- Shape Detection API => 圖像檢測
- Web Workers => 并行計算能力
- ConvNetJS => 深度學習框架
- Tensorflow (原 DeeplearnJS) => 正大力支持 JS
4.2 實際上并沒有那么樂觀
4.2.1 準確率
對于正臉(多個)的識別率還是比較高的,但是在側臉已經有障礙物的情況下,檢測的效果并不理想。
4.2.2 處理速度
對于圖像中人臉檢測的例子2.2,耗費時間300ms+(實際上無法滿足大分辨率視頻實時處理),是調用Opencv的檢測速度100ms的三倍之多。
4.2.3 特性
還有很多需要完善的地方:如不支持眼鏡狀態、性別、年齡估計、表情識別、人種、笑容、模糊檢測等主流服務提供商提供的服務。
4.3 想說又說不完的
a. 本文中所有樣例的源代碼,歡迎 Fork / Star:
https://github.com/x-cold/fac...
https://github.com/x-cold/fac...
b. 關于人臉檢測在不同場景的適應性,以及檢測消耗的時間暫時沒有數據支撐,后面考慮引入PASCAL VOC、AT&T提供的樣本進行小規模的測試。
5 參考
- 人臉識別技術大總結(1):Face Detection & Alignment: http://blog.jobbole.com/85783/
- 阿里巴巴直播防控中的實人認證技術: https://xianzhi.aliyun.com/fo...
- 前端在人工智能時代能做些什么?:https://yq.aliyun.com/article...
- ConvNetJS Deep Learning in your browser:http://cs.stanford.edu/people...
- Face detection using Shape Detection API:https://paul.kinlan.me/face-d...