人臉辨識系統Face Recognition 開發紀錄( OpenCV / Dlib )

文章推薦指數: 80 %
投票人數:10人

此專案利用Pre-train 好的Dlib model,進行人臉辨識(Face Detection) ,並且實現僅用一張照片作為database 就可以作出達到一定效果的人臉識別(Face ... 0% 此專案利用Pre-train好的Dlibmodel,進行人臉辨識 (FaceDetection) ,並且實現僅用一張照片作為database 就可以作出達到一定效果的人臉識別(FaceRecognition)。

除此之外,更加入了活體偵測(LivenessDetection)技術,以避免利用靜態圖片通過系統識別的問題。

整個pipeline是由多個模型所組成,其中包含: 臉部的偵測 人臉識別 雙眼的偵測 開閉眼識別 最後利用開閉眼的偵測來決定是否將人臉識別的結果顯示出來。

Dlib Dlib是一套基於C++的機器學習工具包,藉由Dlib可以使用這些機器學習工具在任何的專案上,目前無論在機器人、嵌入設備、移動設備甚至是大型高效運算環境中都被廣泛使用。

在Window系統中安裝Dlib Dlib跟許多開發套件相同,在Windows系統下非常容易出現安裝上的問題,因此在安裝上面需要花一些時間避坑,以下是筆者安裝成功的一些方法。

pip安裝 簡單一點的方法就是直接在命令提示字元中輸入pip進行安裝 1$pipinstalldlib 上述方式在環境不同的狀況下,可能因為一些依賴項或是系統問題,很有可能會安裝失敗,筆者改輸入下列命令,即可安裝成功,但這樣的安裝方式並不會安裝最新版本的Dlib,而安裝的Dlib也無法調用GPU。

1$python-mpipinstallhttps://files.pythonhosted.org/packages/0e/ce/f8a3cff33ac03a8219768f0694c5d703c8e037e6aba2e865f9bae22ed63c/dlib-19.8.1-cp36-cp36m-win_amd64.whl#sha256=794994fa2c54e7776659fddb148363a5556468a6d5d46be8dad311722d54bfcf 從SourseCode進行安裝 若是希望可以調用GPU運算或是要確保安裝最新版本的Dlib,最推薦的方式還是要直接從SourceCode進行安裝。

首先,先將專案整個clone至本機資料夾中1$gitclonehttps://github.com/davisking/dlib 接著,請確認電腦中有安裝VisualStudio2015,根據實際上測試的結果,VisualStudio2015以外的版本都會導致編譯失敗。

最後在專案位址下輸入1$pythonsetup.pyinstall 正常情況下,在Windows系統中利用此方法進行安裝,應該可以調用GPU,但筆者仍然無法成功使用GPU,這部分的問題仍試圖釐清中。

人臉識別FaceDetection&Recognition 不管是用什麼方式進行人臉識別,基本上都要經過兩個階段的步驟 人臉對齊 身分判斷 先對一張照片、一張Frame找出人臉的位置進行對齊,再利用模型進行特徵萃取來比對出身分。

在這個專案中,我們利用Dlib本身的臉部偵測器來進行人臉對齊後,再使用ImperialCollegeLondon在ibug300-Wdataset所訓練的模型由鏡頭中人臉與資料庫中的人臉同時萃取出關鍵點後進行Embedding,再進行身分比對。

流程簡述 先收集欲辨識的人正面照片(甚至可以收集多角度照片)於特定資料夾(此處設為./rec)中,並將檔名設為人名。

使用dlib.get_frontal_face_detector()擷取資料夾中照片的人臉,再利用dlib.shape_predictor()取出臉部68個關鍵點。

dlib.face_recognition_model_v1().compute_face_descriptor()將68個關鍵點進行嵌入成一個128維的向量\(\nu_1,\nu_2,\cdots\)。

相同的方式將鏡頭中的人臉也嵌入成128維的向量\(\nu\)。

計算\(\nu\)與\(\nu_1,\nu_2,\cdots\)個別計算歐式距離,最接近者及判定其身分。

模型路徑ModelPath 我們先將要使用的模型路徑設定好, 123456789#人臉對齊detector=dlib.get_frontal_face_detector()#人臉關鍵點模型predictor=dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')#128維向量嵌入模型face_rec_model_path="dlib_face_recognition_resnet_model_v1.dat"facerec=dlib.face_recognition_model_v1(face_rec_model_path) 人臉嵌入FaceEmbedding 將每一個資料庫中的資料進行人臉各嵌入成一個128維度向量,並且收集所欲判定的人名。

12345678910111213141516171819202122#比對人臉描述子列表descriptors=[]#欲比對人臉名稱列表candidate=[]#針對比對資料夾裡每張圖片做比對:forfinglob.glob(os.path.join(faces_folder_path,"*.jpg")):base=os.path.basename(f)#依序取得圖片檔案人名candidate.append(os.path.splitext(base)[0])img=io.imread(f)#1.人臉偵測dets=detector(img,0)fork,dinenumerate(dets):#2.特徵點偵測shape=predictor(img,d)#3.取得描述子,128維特徵向量face_descriptor=facerec.compute_face_descriptor(img,shape)#轉換numpyarray格式v=numpy.array(face_descriptor)descriptors.append(v) 相同的方式,配合鏡頭擷取出來的Frame來將畫面中的人臉嵌入成128維向量。

身分判別FaceRecognition 1234567#計算歐式距離foriindescriptors:dist_=np.linalg.norm(i-d_test)dist.append(dist_)#將比對人名和比對出來的歐式距離組成一個dictcd=dict(zip(candidate,dist))cd_sorted=sorted(c_d.items(),key=lambdad:d[1]) 使用np.linalg.norm()直接計算嵌入向量的距離,並將人名及相對應計算出來的距離以Dictionary方式呈現,排序後取最高者作為判斷結果。

上面的流程就是單純人臉身分判斷的流程及部分程式碼解析,這樣的方式應用在Windows系統中Inferencetime稍長大概是唯一的問題,其判別的準確度筆者認為並不算太差。

活人偵測LivenessDetection 在筆者實作人臉辨識專案的同時,意外地看到了一篇挺有趣的新聞:"刷臉被破解!小學生拿「彩色照」秒解鎖 側臉、偷拍都能開",讓筆者不禁思考,如何可以在不另外安裝硬體設備(譬如:深度相機、紅外線鏡頭...等)下,盡可能地避免這樣的狀況發生? 搜尋了一些資料,以目前的狀況大約有兩個方向可行:(1)直接訓練一個DeepLearningModel判斷人臉真假,(2)利用眨眼的過程進行真實人臉的判斷。

在此專案中,筆者採用了後者的方式進行LivenessDetection。

眨眼偵測,筆者使用了JordanVanEetveldt預訓練好的左右眼開闔判別模型,先偵測鏡頭捕捉的眼睛是開啟還是閉眼。

再來配合簡單的邏輯判斷,當偵測眼睛的過程中出現了開、閉、開的過程,即判斷為真人,將前述的人臉辨識結果呈現出來。

定義函式 這邊主要定義三個函式,載入預訓練模型、進行開閉眼預測、以及邏輯判斷眨眼狀態: 12345678910111213141516171819202122232425262728293031defisBlinking(history,maxFrames):#偵測眼睛狀態是否有開、閉、開這樣的連續動作出現foriinrange(maxFrames):pattern='1'+'0'*(i+1)+'1'ifpatterninhistory:returnTruereturnFalsedefpredict(img,model): img=Image.fromarray(img,'RGB').convert('L') img=imresize(img,(24,24)).astype('float32') img/=255 img=img.reshape(1,24,24,1) prediction=model.predict(img) ifprediction<0.1: prediction='closed' elifprediction>0.9: prediction='open' else: prediction='idk' returnpredictiondefload_model(): json_file=open('model.json','r') loaded_model_json=json_file.read() json_file.close() loaded_model=model_from_json(loaded_model_json) #loadweightsintonewmodel loaded_model.load_weights("model.h5") loaded_model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy']) returnloaded_model 載入模型LoadModel 123456789open_eye_cascPath='C:\pythonwork\Facedetection\haarcascade_eye_tree_eyeglasses.xml'left_eye_cascPath='C:\pythonwork\Facedetection\haarcascade_lefteye_2splits.xml'right_eye_cascPath='C:\pythonwork\Facedetection\haarcascade_righteye_2splits.xml'open_eyes_detector=cv2.CascadeClassifier(open_eye_cascPath)left_eye_detector=cv2.CascadeClassifier(left_eye_cascPath)right_eye_detector=cv2.CascadeClassifier(right_eye_cascPath)model=load_model() 真人判定LivenessDetection 一開始,系統僅會偵測眼睛,雖然同時也會對人臉進行辨識,卻不會顯示出來。

而這個部分定義了,在什麼樣子的狀態下,才會將人臉辨識的結果呈現出來。

12345ifisBlinking(eyes_detected[rec_name],3):cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)#Displaynamey=y-15ify-15>15elsey+15cv2.putText(frame,rec_name,(x,y), 後記 其實看了此文介紹的人臉辨識,用了兩三個模型進行最終的人臉判別,其實如果有看過FaceNet論文"FaceNet:AUnifiedEmbeddingforFaceRecognitionandClustering"其概念幾乎完全一樣,但是用了更快的方法來達成而已,或許,這個專案未來可以試著用FaceNet來替代Dlib的方式進行辨識。

另外,這種LivenessDetection的方式是否能完全杜絕人臉辨識被破解?其實不然,基本上利用一個人臉有眨眼的影片或許也可以破解這個部分,但是正如筆者所提到的,真正萬無一失的辦法還是得另外安裝硬體設備,單純使用深度學習的方式或許盡可能可以做到的就是如此。

參考資料 Real-timefacelivenessdetectionwithPython,KerasandOpenCV LivenessDetectionwithOpenCV 基於python語言使用OpenCV搭配dlib實作人臉偵測與辨識



請為這篇文章評分?