Shape Detection API 的發佈已經有一些時日,其主要的提供的能力是給予前端直接可用的特徵檢測的接口(包括條形碼、人臉、文本檢測)。本文將簡單的對其進行介紹,對前端進行人臉檢測進行普適性的講解。(本文不講算法~望輕拍)html
人臉檢測(Face Detection)算是老生常談的課題了,在諸多行業應用普遍,例如金融、安防、電子商務、智能手機、娛樂圖片等行業。其中涉及的技術也在不斷的演變,下面簡要介紹幾種思路:前端
a. 基於特徵的人臉檢測node
例如opencv中內置了基於Viola-Jones目標檢測框架的Harr分類器(實際上大多數分類器都是基於學習獲得的),只須要載入對應的配置文件(haarcascade_frontalface_alt.xml)就能直接調用detectObject去完成檢測過程,同時也支持其餘特徵的檢測(如鼻子、嘴巴等)。jquery
b. 基於學習的人臉檢測,其實也是須要經過算子提取的圖像中的局部特徵,經過對其進行分類、統計、迴歸等方式獲得的具有更精確和快響應的分類器。git
前端經過網絡將資源傳輸到後端,後端統一處理須要檢測的圖像或視頻流,對後端的架構有必定的挑戰,同時網絡的延時每每不能給用戶帶來實時的交互效果。github
得益於OpenCV在跨語言和跨平臺的優點,客戶端也能以較低的開發成本的提供人臉檢測的能力,而且能夠經過JsBridge等方式向web容器提供服務,然而一旦脫離這個容器,孤立的頁面將失去這種能力。直到有一天……web
不知道從啥時候開始,雲計算等概念拔地而起,計算的成本日益下降。各大研發團隊(如阿里雲、Face++)都蠢蠢欲動又不緊不慢的上架了人臉檢測服務,甚至還帶上了各類特!殊!服!務!,人臉識別、活體識別、證件OCR及人臉對比等等等。算法
儘管不只提供了客戶端的SDK以及先後端的API,可是,怎麼說也要講講我純前端的方案吧。chrome
好吧,人臉識別在前端依然是在刀耕火種的遠古時代,然而,咱們的基礎建設已經起步,但願後續的一些相關介紹能爲各位看官帶來必定的啓發。canvas
隨着客戶端硬件的計算能力逐漸提升,瀏覽器層面獲得的權限也愈來愈多,因爲圖像處理須要耗費大量的計算資源,實際上瀏覽器上也能承擔圖像檢測的一些工做,所以就搞出了個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));
圖像的人臉檢測比較簡單,只須要傳入一個圖片的元素,就能直接調起該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)); }
處理效果:
視頻中的人臉檢測跟圖像相差不大,經過
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);
處理效果:
實際上,在好久好久之前,也有很多解決方案存在。因爲硬件條件以及沒有硬件加速等限制的狀況,一直沒有被普遍地投入生產。
a. tracking.js
tracking.js 是一款js封裝的圖像處理的庫,爲瀏覽器帶來豐富的計算視覺相關的算法和技術,經過它能夠實現顏色追蹤、人臉檢測等功能,具體特性以下:
b. jquery.facedetection
jquery.facedetection 是一款jquery / zepto 人臉檢測插件,基於跨終端能力超強的ccv中的圖像分類器和檢測器。
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.2.1 準確率
對於正臉(多個)的識別率仍是比較高的,可是在側臉已經有障礙物的狀況下,檢測的效果並不理想。
4.2.2 處理速度
對於圖像中人臉檢測的例子2.2,耗費時間300ms+(實際上沒法知足大分辨率視頻實時處理),是調用Opencv的檢測速度100ms的三倍之多。
4.2.3 特性
還有不少須要完善的地方:如不支持眼鏡狀態、性別、年齡估計、表情識別、人種、笑容、模糊檢測等主流服務提供商提供的服務。
a. 本文中全部樣例的源代碼,歡迎 Fork / Star:
https://github.com/x-cold/fac...
b. 關於人臉檢測在不一樣場景的適應性,以及檢測消耗的時間暫時沒有數據支撐,後面考慮引入PASCAL VOC、AT&T提供的樣本進行小規模的測試。