撰寫/攝影 | CH.Tseng |
部落格 | https://chtseng.wordpress.com/ |
https://www.facebook.com/chenghsun.tseng |
以往…當週遭的親朋好友們聽到上班的公司不用打卡時,總會露出欽羨的表情,認為這才是美式作風的信任與自由,但是隨著向下的薪資漲幅曲線與老闆嘴唇的微笑曲線呈現死亡交叉之後,大家才猛地發覺原來上下班強制刷卡才是保障員工福利、反映實際工時的好方法,於是勞基法也要求公司必須提供並妥善保存員工每日的打卡記錄。
為了要打卡,一張張被戲稱為狗牌的RFID卡片成了上班族的標準配飾,有的人掛在脖子、有的人別在胸前、有的人放在褲袋或皮包,但無論怎麼擺放,還是不像悠遊卡放在身上那麼讓人心甘情願。有鑑於目前各種開源的臉部識別軟體這麼盛行,我們何不DIY一台臉部識別刷卡機來取代刷卡呢?只要一台樹莓派加上LCD螢幕,一支Movidius神經運算棒,再加上兩支web camera,就能完成一台辨識速度和準確率足敷所需的人臉辨識打卡機了,就算忘了帶識別卡片也沒關係。
單機板與Edge版
文中所謂的樹莓派單機板,代表所有的影像處理與辨識推論都在樹莓派本機上完成(僅最後的刷卡登錄及開門動作是送出指令由後端機器執行),未來我們也將試作如下的Edge版本,以便適合多台刷卡鐘情境的建置。
樹莓派單機版 | 樹莓派Edge版 |
材料及組裝:
首先準備下列的材料:
- Intel Movidius Stick一代。
- 樹莓派3 B
- 樹莓派官方7” 觸控LCD
- Web Camera二支。建議HD畫質,本範例用的是Logitech C270 HD。
- USB 3.0 HUB,接多個USB裝置使用。
- 隨身碟(儲存相片)、按鈕、音源增益模組+揚聲器(也可以直接用喇叭)。
- LED燈+繼電器模組。補光用,如果現場環境夠亮可不需要。
材料使用的補充說明
樹莓派官方版七吋觸控LCD
官方所出的觸控LCD套件,安裝簡單使用方便且不需額外的driver。只是要注意這個板子裝到樹莓派後,整體需要的電量極大,至少要2.5A以上的USB電源轉換器才能正常驅動。
將排線接到樹莓派的MIPI DSI display port,另外再接上5V及GND就完工了。
兩支USB web camera
如果僅使用一支web camera來拍攝臉孔進行辨識,那麼我們要非常擔心使用者可能直接用平面的相片或手機畫面來矇騙過關,是故,我們同時使用兩支camera來拍攝不同角度的臉孔,應可避免這個問題。
本刷卡系統設計為同時拍攝兩張不同角度的人臉相片來析,除了正面的鏡頭外,另一支鏡頭的角度您可自行選擇從半側面、上方或下方來拍攝。
使用隨身碟或網路磁碟儲存
由於希望將所有資訊,包含使用者在辨識時所拍的相片、使用記錄等都要儲存下來,以利後續追蹤改善並提供人事單位備查,因此IO的讀寫會很頻繁,使用外接儲存方式將所有資訊存在隨身碟或直接傳送到網路硬碟,以避免直接儲存到樹莓的OS SD disk是比較理想的作法。
加入語音功能
由於希望使用者在操作時能有語音的輔助,因此設計讓系統在每個步驟前唸出提示。使用音源增益模組(如GF1002)加上揚聲器,可避免使用體積較大的喇叭,且GF1002的聲音品質及音量在可接受範圍內。
使用USB HUB擴充樹莓的USB介面
Movidius Neural Stick體積相當大,插到樹莓派後會發現除了本身佔用一個還會佔據左右側的空間,因此原本四個USB插槽只剩二個可使用,此時若想再接USB keyboard、mouse、web cam、以及外接儲存用的隨身碟,勢必得加上USB HUB擴充才行。
所有的材料及零件的連接方式就如同下圖。
Button | 繼電器 | |
功能說明 | 按下後開始辨識 | 開始拍照時開啟LED |
GPIO腳位 | 15 | 18 |
最後使用3D printer列印外殼
外殼設計重點:
- 希望可吊掛於牆上。
- 內部空間可放置LCD、樹莓派、Movidius StickUSB HUB、音源模組等。
- Web camera可固定於上下方。
- 可放置一個按鈕用來進行辨識。
左側為前方外殼,右側為固定於牆壁的後殼。
組裝完成外觀
您可從https://github.com/ch-tseng/RPI_Facenet_Movidius_V1/raw/master/face.stl 與https://github.com/ch-tseng/RPI_Facenet_Movidius_V1/blob/master/wall.stl下載該3D stl檔來列印。
樹莓與Intel Movidius Stick的安裝設定
Movidius的NCAPPZOO提供了Tensorflow版本的Facenet model sample,執行起來速度相當不錯。請先下載並安裝最新版的Raspbian OS之後,再將Neural Compute Stick插到USB,開始在樹莓派進行NCSDK安裝。
步驟:
1.安裝下列套件:(可將下列內容放置於shell檔中一次執行比較方便)
sudo apt-get update
sudo apt-get upgrade –y
sudo apt install python-pip python3-pip
sudo apt-get install -y libusb-1.0-0-dev libprotobuf-dev
sudo apt-get install -y libleveldb-dev libsnappy-dev
sudo apt-get install -y libopencv-dev
sudo apt-get install -y libhdf5-serial-dev protobuf-compiler
sudo apt-get install -y libatlas-base-dev git automake
sudo apt-get install -y byacc lsb-release cmake
sudo apt-get install -y libgflags-dev libgoogle-glog-dev
sudo apt-get install -y liblmdb-dev swig3.0 graphviz
sudo apt-get install -y libxslt-dev libxml2-dev
sudo apt-get install -y gfortran
sudo apt-get install -y python3-dev python-pip python3-pip
sudo apt-get install -y python3-setuptools python3-markdown
sudo apt-get install -y python3-pillow python3-yaml python3-pygraphviz
sudo apt-get install -y python3-h5py python3-nose python3-lxml
sudo apt-get install -y python3-matplotlib python3-numpy
sudo apt-get install -y python3-protobuf python3-dateutil
sudo apt-get install -y python3-skimage python3-scipy
sudo apt-get install -y python3-six python3-networkx
sudo pip3 install opencv_contrib_python
sudo apt-get install -y libatlas-base-dev
sudo apt-get install -y libjasper-dev
sudo apt-get install -y libqtgui4
sudo apt-get install -y libqt4-test
sudo apt-get install -y python3-pyqt5
sudo pip3 install imutils
sudo apt install -y cython
sudo -H pip3 install cython
sudo -H pip3 install numpy
sudo -H pip3 install pillow
sudo pip3 uninstall tensorflow
wget https://github.com/lhelontra/tensorflow-on-arm/releases/download/v1.7.0/tensorflow-1.7.0-cp35-none-linux_armv7l.whl
sudo pip3 install tensorflow-1.7.0-cp35-none-linux_armv7l.whl
rm tensorflow-1.7.0-cp35-none-linux_armv7l.whl
確認OpenCV及Tensorflow的安裝是否完成:
python3
>>> import cv2
>>> import tensorflow
2.加大swap size:
sudo nano /etc/dphys-swapfile
將CONF_SWAPSIZE由預設的100(MB)增加為1024(MB)以上。接著重啟dphys-swapfile service。
sudo /etc/init.d/dphys-swapfile restart
3. 安裝NCSDK:
cd ~; git clone -b ncsdk2 http://github.com/Movidius/ncsdk
cd ncsdk/
nano ncsdk.conf → 將#MAKE_NJOBS=1前方的mark #移除
sudo make install
這個install的過程在樹莓派上相當久,約需要 2-3小時。之後,會看到如下方的訊息,即安裝完成。
修改sudo nano /etc/dphys-swapfile
將CONF_SWAPSIZE還原為預設的100(MB)再重啟dphys-swapfile service。
sudo /etc/init.d/dphys-swapfile restart
4.測試是否work
cd ~/ncsdk/examples/apps/hello_ncs_py/
make run
使用模式設計
為了方便各種使用情境,該刷臉系統設計了三種使用模式,以及一個管理者使用的新增user模式,預設為模式二。
使用模式一:輸入工號&全公司人臉比對
使用者按鈕刷臉後接著輸入自己的工號,系統便將拍攝者的臉孔與全公司臉孔進行比對,取得最接近且低於門檻值的工號,若該工號與使用者輸入的工號一致,則認定為該員工本人無誤。
使用模式二:輸入工號&比對該工號人臉
使用者按鈕刷臉後接著輸入自己的工號,系統便開始比對系統中該工號的臉孔與拍攝者的臉孔是否一致且低於門檻值,若是的話則認定為該員工本人無誤。
使用模式三:不需輸入工號 & 比對全公司人臉
使用者按鈕刷臉後不需要輸入工號,系統便開始比對全公司的臉孔與拍攝者的臉孔,取出最相近者並檢查相似度是否低於門檻值,若是的話則認定拍攝者為該員工。
安全性:
模式一 > 模式二 > 模式三
- 模式一要求使用者的臉孔與輸入的員工工號,必須與全公司臉孔最相似的那位員工ID一樣,不單單只要低於相似門檻值即可,因此在這三種模式中是安全性最高的。
- 模式二不比對全公司員工,在使用者輸入工號之後,系統僅會比對該臉孔與拍攝者的臉孔其相似度是否低於門檻值,是的話則通過認定。
- 模式三僅要求使用者刷臉而不需輸入工號,系統抓取全公司員工的臉孔與拍攝者的臉孔進行比對,取得最相似的那一張且其相似度低於設定的門檻,則通過認定。
方便性:
模式三 > 模式二 > 模式一
對於使用者來說,模式三是最簡單方便的,因為只要按鈕刷臉即可,若通過驗證就會自動刷卡開門。模式二與模式一皆需要刷臉與輸入工號,因此對使用者來說操作上並沒有差別。
使用者刷臉打卡開門的時間:
模式一 > 模式三 > 模式二
模式一與三都需要進行全公司人臉比對,但模式三不需要輸入工號,因此省了工號輸入的操作時間。模式二雖然也要輸入工號,但僅比對拍攝者的工號與臉孔是否相符,對使用者來說模式二所需要的等待時間最少。
V: necessary O: time
模式一 | 模式二 | 模式三 | |
輸入工號 | V | V | |
比對所有人臉 | V | V | |
對使用者方便操作 | O | OO | OOOO |
使用者打卡所需時間 | OOOO | OO | O |
對於資源有限的樹莓派來說,模式二是折衷後最佳的選擇。
給管理者的新增模式
本模式提供給管理員使用,當管理員透過臉卡辨識成功後,若在10秒鐘內再次按下辨識鈕則進入新增模式,可開始輸入員工工號註冊或增加比對用的臉孔相片。
使用情境及注意事項
1.給使用者一些在鏡頭前的準備時間,避免使用者還沒擺好pose或還在移動中,系統就已經偵測並取得臉孔開始辨識。
- 改善方式:使用者按下按鈕並顯示預覽畫面之後,讓系統等待指定的秒數後才開始偵測臉孔,可讓使用者在預覽畫面中先調整好角度姿勢。
2.某些偵測到臉孔位於影像邊緣,可能導致部份偵測到的臉孔是不完全的。
- 改善方式:設定偵測時臉部中心點不可超過影像中心點週圍的設定範圍內。
3.畫面中除了使用者,背後還有其它非相干的臉孔一同入鏡。
- 改善方式:設定只取最大的那張臉孔,且其尺寸必須大於設定的大小。
4.不同角度的camera計算出的差異程度不同:
- 改善方式:兩支camera所拍攝的角度不同,其通過辨識的分數也不同,因cam0與cam1應分別有不同的threshold值,而非共用相同的值。
0.2581734 / 0.8671345 Pass / Failed |
0.1392377 / 0.8281625 Pass / Failed |
5.由於使用者移動造成取得的影像模糊,影響辨識結果:
- 改善方式:使用OpenCV提供的cv2.Laplacian再取其變異數,如:cv2.Laplacian(gray, cv2.CV_64F).var(),其值愈高代表圖片愈清楚。
6.某個使用者經常發生辨識失敗的情況:
- 改善方式:辨識時,系統會依序讀取該工號資料夾中的人臉相片與目前拍攝者的相片進行比對,若其差異度低於threshold值則認定為同一人。因此,同一位使用者可以有多張臉部相片供比對,例如,有戴眼鏡與摘下眼鏡、有戴口罩與未戴口罩、張嘴與閉著嘴等。
7.系統很難detect到face:
- 改善方式:注意現場環境光源,無論整體夠不夠亮,只要是背光的環境,無論快速的Haar Cascade、強悍的Dlib或深度學習的MTCNN,都很難偵測到臉孔甚至容易誤判,因此視環境需求來打光是必要的。
Facenet的使用及辨識計算
此部份請參考另一篇知識文件的介紹:「Facenet介紹與使用」
主程式放置於:https://github.com/ch-tseng/RPI_Facenet_Movidius_V2.git,請如前述將硬體組裝好並安裝NCSDK之後,git clone程式下來,確認並修改下列參數後,執行python3 main.py便可執行。
參數說明:
#要使用何種臉部偵測技術?四種可選:dlib / cascade / mtcnn / mtcnn2,MTCNN與MTCNN2的差別在於,MTCNN是修改自https://github.com/ipazc/mtcnn,而mtcnn2是修改自ncappzoo
faceDetect = "cascade"
#本系統是否只淮許在上班時間運作?
onlyWorkDay = True
#若只淮許在上班時間運作,請設定下方的休假日期
notWorkDay = [ "2/4", "2/5", "2/6", "2/7", "2/8", "2/28", "3/1", "4/4", "4/5", "5/1", "6/7", "9/13", "10/10", "10/11" ]
#系統的執行模式,如上文所述,有三種模式。
runMode = 2
#隨身碟的路徑
topDIR ="/media/pi/3A72-2DE1/"
#拍攝的相片要放置於本機的webroot下,提供透過URL來讀取. (請安裝apache2或lighthttpd)
toWebserver = "/var/www/html/door/"
#設定logging記錄檔
logging.basicConfig(level=logging.INFO, filename=topDIR+'logging.txt')
#for Movidius Stick的Facenet model
GRAPH_FILENAME = "facenet_celeb_ncs.graph"
#語音wav檔的path
WAV_FOLDER = "/home/pi/works/door_face/wav/"
#cam0 的分數要低於多少才算通過辨識
FACE_MATCH_THRESHOLD_cam0 = 0.35
#cam1 的分數要低於多少才算通過辨識
FACE_MATCH_THRESHOLD_cam1 = 0.35
#cam0與cam1 的平均分數要低於多少才算通過辨識
FACE_MATCH_THRESHOLD_avg = 0.35
#設定相機所拍攝的解析度
webcam_size = ( 640,480)
#拍攝的相片是否要旋轉?
cam1_rotate = 0
cam2_rotate = 0
#開始辨識按鍵的GPIO腳位
btnCheckin = 15
#打開LED補光燈的GPIO腳位
pinLight = 18 #LED燈pin
#有權限進入管理模式的工號(使用此工號登入可進行新使用者的註冊)
adm_users = [200999]
#等待幾秒再開始辨識, 免得使用者還沒準備好就拍了相片並辨識了
wait_to_detectFace = 6
#拍照時,cam0的中心要在紅框中間多大的距離內才行
offsetFaceBox = (10,10)
#拍照時間超過幾秒沒有動作,則回到等待狀態
captureTime = 60
#相片是否清楚的threshold,高於此值才算清楚,否則會繼續detect face
blurRate = 120 # higher is more clear, lower is more blurly
#所有拍攝到的臉部相片, 都會放置於此path
historyPicPath = topDIR+"history/" #for those face is pass the required size and will be check
#存放有註冊使用者供比對的人臉相片
validPicPath = topDIR+"valid/"
#OpenCV Haar Cascade file的path,如果你並非使用Cascade Haar來detect face則可忽略
face_cascade = cv2.CascadeClassifier('cascade/haarcascade_frontalface_default.xml')
#設定Cascade Haar的參數
cascade_scale = 1.1
cascade_neighbors = 8
minFaceSize = (120,120)
#cam0與cam1臉部area尺寸最小不可低於
minFaceSize1 = (120, 120)
minFaceSize2 = (90, 90)
#設定DLIB detect face的偵測比率,如果你並非使用DLIB detect face則可忽略
dlib_detectorRatio = 0
#後端打卡記錄的Post URL
posturl="http://api.sunplusit.com/api/DoorFaceDetection"
後端系統動作
當使用者執行刷臉完畢後,樹莓派便會運行Facenet透過Movidius stick計算其Embedding features與登記在系統中的臉孔圖片差距,若低於threshold則認定刷卡成功,否則失敗。無論成功或失敗,這項刷卡記錄皆會透過URL Post給後端的web server,儲存到資料庫中。這部份感謝公司的負責web的大神Vincent大力協助。
若刷卡成功,web server會同時publish開門訊息給MQTT server,負責控制大門口開關的裝置(也是樹莓派)收到後,便會把門打開讓刷卡者進來。整個刷卡過程的相片皆會儲存到資料庫中,因此人事部門的同仁可即時的在網頁上查詢到刷卡記錄,包含刷卡當時所拍攝的臉孔相片。
人臉辨識刷卡的執行示範
想了解更多CH.Tseng,可以點此連結劉瀏覽更多文章喔~
您好,非常用心的分享,想請問一下若我想製作此臉部辨識打卡機,也可以使用Raspberry pi 3 B+來製作嗎?謝謝~
您好,當然可以喔
請問一下 如果沒有神經運算棒 還可以做人臉辨識嗎?
您好,當然可以。單獨使用 Rpi 就可做到,只是速度較慢。NCS 是用來加速視覺推論的速度
請問一下,如果換成神經運算棒第二代,是不是改了驅動程式就可使用了?
Zheng You Yun 你好:
可以參考blog: https://blog.cavedu.com/2019/08/20/openvino2/