前端工程師作Face Detection

由於項目緣由,須要使用人臉檢測(face detection)功能。身爲一名前JAVA業務程序員和現前端程序員,這樣的功能仍是陌生的領域。那能不能經過搜索和學習能力,加上已有的編程思想,快速實現功能呢?這就是這篇文章的重點,憑藉本身的技術與積累,走向本身不熟悉的領域。html

需求

使用PC加攝像頭,經過人臉檢測,完成自動拍照功能。在PC的屏幕上,顯示攝像頭的實時畫面,要是畫面中檢測出人臉,則觸發拍照。前端

抽其關鍵點:攝像頭,實時畫面,人臉檢測,和拍照node

本身擁有的技能

項目並無要求開發應用的類型,那麼我確定是先從自身擁有的技能出發,看是否能尋求解決方案。身爲前端,深知前端技術潛力無限,確定有本身還不知道的技術。果不其然,找到了Tracking.jsgit

Tracking.js是一個頗有意思的庫,體積小巧,在瀏覽器上,直接經過JS提供一些基本的Computer Vison相關的功能,如人臉檢測(face detection),顏色識別(color detection),特徵識別(feature detection)。關鍵是,出了對靜態圖片可以進行識別和處理以外,還可以直接對視頻(video)和攝像頭(webcam)視屏流進行處理,這就基本給出了人臉識別的方案。程序員

那如何拍照呢?我找到了WebcamJS。可以在瀏覽器上讀取攝像頭視頻流,調用函數截取某個時刻視頻流幀爲圖片,即視爲拍照。github

解決方案一

兩個庫一結合,就有了初步的解決方案,實現了功能,簡單快速。web

人臉檢測能力不足

在Tracking.js的官網上能夠看到,demo的視頻尺寸都是很小的,320 * 240,纔能有30FPS的處理速度。尺寸若是大了,則識別速度慢,卡頓明顯。項目中視頻顯示大小基本爲1080P分辨率屏幕的三分之一,直接處理這個大小的視頻,速度確定不夠。就算我不直接對大尺寸視頻流進行處理,轉而對一個隱藏的小尺寸視頻流處理,將人臉位置映射到大視頻流中,速度上沒問題,可是可檢測的人臉大小就有限了,即人必須離攝像頭比較近才能被檢測到。編程

視頻流的清晰度不夠

使用的是羅技的1080P的網絡攝像頭,可是在瀏覽器上可以看到的,好像並無以1080P的分辨率進行展現。嘗試了一些參數的修改,可是結果都不盡人意。瀏覽器

人臉識別形成性能問題

實時的視頻流人臉識別,是很耗CPU的,下圖中右邊那個藍色的陡坡就是在我關閉了Tracking.js的demo頁面後CPU降低的曲線。服務器

這種狀況下,想添加一些傳統的網頁動效,簡直卡出翔來。(關於這點,使用web worker進行人臉檢測的工做,應該能有所幫助,可是本身並無往這方面走)

繼續尋找方案

爲了尋找上面的問題的解決辦法,我瞭解到了Tracking.js和WebcamJS的運行原理。好比在瀏覽器上獲取攝像頭視頻流,是經過getUserMedia,是基於WebRTC的支持。

WebcamJS就是經過getuserMedia()方法,得到攝像頭的視頻流信息,做爲<video>標籤的src屬性,歷來可以在網頁上進行顯示實時畫面。經過CanvasdrawImage()方法,將video標籤傳入,便可繪製那個時刻視頻幀的圖像。(也是經過此次機會我才瞭解到drawImage()原來還能夠接受HTMLVideoElement做爲參數的)

以前就知道,通常作計算機視覺的,都會用opencv庫,這是個C++的庫。同時又查到了,有人在node上作了opencv的擴展,而且看到了這個Github項目。因而爲了檢測效果,本身作了嘗試。

解決方案二

經過上面的學習,我已經可以在瀏覽器段獲取攝像頭的幀圖像,而且知道opencv能作人臉檢測。那麼此次的方案思路就是:將視頻流的幀圖像,經過websocket發到後臺服務器上,在服務器裏使用opencv進行人臉分析,將人臉的座標發送到前端。

這裏後臺我並無使用node-opencv,而是使用QT直接作websocket服務器和調用opencv庫(仗着本身曾也學過C++,就大膽的直接奔着C++去了)。

可是結果也不理想,緣由以下。

發送圖像給後臺耗時大

將圖片發送給後臺,首先想到的是使用Canvas的toDataURL()方法,將圖片轉成base64字符串,發給後臺。但實測該方法很慢!640 * 480大小的圖片,經過toDataURL(),大體須要50ms時間。

而後考慮使用getImageData(0, 0, 640, 480)方法,獲取圖片像素信息,而後轉成字符串發到後臺。經測,該方法比toDataURL()確實快很多,大體在5ms左右。可是將它轉成JSON字符串,則很慢很慢。

最後查到,toDataURL('image/jpeg')會加快速度,由於這裏不須要計算Alpha通道。實測,小於10ms。

以前有擔憂的網絡傳輸耗時問題,卻是獲得了證明,這個擔憂是沒有必要的。由於是本地傳輸,經過websocket傳輸一張圖片(小尺寸或者大尺寸)base64字符串大小的內容,耗時都很小,算下來FPS可以上50。

CPU消耗大

Approach CPU %
QT Opencv Face Detection 30%
Tracking.js Face Detection 50%
Websocket + Opencv 90%

不肯定本身在實現上是否哪裏出了問題,致使這麼高的CPU使用率。但無論怎麼,仍是放棄了這個方案。

解決方案三

居然都使用上了QT,就大步向前走好了,畢竟這樣的圖像處理程序,仍是作桌面應用是作合適的。何況QT體系中的QML語言,可以使用JS,學起來有點像在學一個新的前端MVVM框架,好感度和信心瞬間提高很多。

使用QML作界面,使用CameraVideoOutput組件進行攝像頭視頻的實時顯示,這裏能指定顯示分辨率和FPS,很方便;配合使用QVideoFilterRunnableQAbstractVideoFilter類對幀進行處理,異步返回給主界面人臉檢測的結果;opencv和另一個能作人臉識別的C++庫Dlib結合使用,可以完成640 * 480尺寸的30FPS處理。

再優化!給每一幀圖片進行人臉識別,速度和識別能力均可以提升,就是經過Dlib中提供的Video Object Tracking來完成。一旦對某一幀可以檢測到人臉以後,對以後的幀執行該人臉區域圖像的tracking。這樣作的效果可以得到更高的FPS,同時tracking還能完成更遠距離臉部的捕獲。

到這裏,方案才以爲差很少了。

總結

面對項目中本身的未知領域,若是不缺錢,那麼直接買商業解決方案。Visage Tech提供的HTML5的人臉識別解決方案(好像用了WebAssembly),簡直變態:快速!準確!穩定!核心科技就是和咱們這些小打小鬧的不同。

若是不購買商用解決方案,那麼應該儘可能找到可以幫助本身的朋友,指條正確的方向可以節省不少調查摸索的時間。好比,若是需求要求程序在拍照時還能控制外接的燈泡,完成閃光燈的效果。那麼如何使用軟件完成對外部硬件的控制呢?這樣的功能對於我這個非計算機專業的而言,真是蒙圈了。最後仍是經歷的大半天的摸索,才找到GPIO的解決辦法。

提升編程的素養,擴大本身的興趣面,熱愛技術,善於google,邏輯思路清晰,那麼在面對不熟悉的領域,新的技術,也可以找到解決方案。而且這個過程能讓本身得到很多知識,face detection, object tracking, tracking.js, webcamJS, getUserMedia(), toDataURL()的性能,opencv,dlib,QML,GPIO,樹莓派,我還差點去現學了Python。這些東西沒有必要都是深究,可是知道他們的存在,會給擴展本身的思路。

相關文章
相關標籤/搜索