你可以在網際網路上找到的大多數面部識別算法和研究論文都受到照片攻擊。這些方法在檢測和識別來自網絡攝像頭的圖像、視頻和視頻流中的人臉方面非常有效。然而,他們不能區分活人的臉和照片上的臉。這是因為這些算法適用於2D frames。
現在讓我們想像一下,我們想要實現一個面部識別開門器。該系統能夠很好地區分已知面孔和未知面孔;以一種只對授權人開放的方式。儘管如此,對於一個懷有惡意的人來說,只展示授權人的照片是很容易的。這就是3D探測器適用的地方,就像蘋果公司的FaceID一樣。但是如果我們沒有3D探測器呢?

本文的目的是實現一種基於眨眼檢測的人臉活性檢測算法,以阻止照片攻擊。該算法通過網絡攝像頭實時工作,只有在對方眨眼時才顯示其姓名。該程序運行如下:
檢測攝像頭生成的每個幀中的人臉。對於每個檢測到的臉,檢測眼睛。對於每個檢測到的眼睛,檢測眼睛是睜著的還是閉著的。如果在某一時刻檢測到眼睛是睜開的,然後又閉上,然後再睜開,我們就得出結論,這個人眨眼了,程序就會顯示它的名字(在面部識別開門器的情況下,我們會授權這個人進入)。對於人臉的檢測和識別,您需要安裝face_recognition庫,它提供了非常有用的深度學習方法來查找和識別圖像中的人臉。特別是face_locations、face_encodings和compare_faces函數是最有用的3個函數。face_locations方法可以使用兩種方法檢測人臉:梯度直方圖(HoG)和卷積神經網絡(CNN)。本文選擇HoG方法。face_encodings函數是一個經過預處理的卷積神經網絡,它能夠將圖像編碼成包含128個特徵的向量。這個嵌入向量應該表示足夠的信息來區分兩個不同的人。最後,compare_faces計算兩個嵌入向量之間的距離。它將允許我們識別從網絡攝像頭幀中提取的人臉,並將其嵌入向量與我們數據集中所有編碼的人臉進行比較。最接近的向量應該對應於同一個人。
1.已知的面部數據集編碼
該算法能夠識別自己和巴拉克歐巴馬。我選了大約10張照片。下面是處理和編碼已知面部數據集的Python代碼。
現在我們知道了我們想要識別的每個人的編碼,我們可以嘗試通過網絡攝像頭識別和識別人臉。但是,在此之前,我們需要區分面部照片和活人臉部。
2.人臉活性檢測
提醒一下,我們的目標是在某一時刻檢測到眨眼動作。我訓練了一個卷積神經網絡來區分眼睛是睜著還是閉著。選擇的機器學習模型是LeNet-5,該機器學習模型已經在Closed Eyes In The Wild(CEW)數據集上進行了訓練。它由大約4800張24x24大小的眼睛圖像組成。完整機器學習模型的Python代碼如下:
在評估此機器學習模型時,準確率達到了94%。
每次我們檢測到一隻眼睛,我們就用我們的機器學習模型預測它的狀態,並跟蹤眼睛狀態。因此,使用下面的函數,檢測眨眼變得非常容易,該函數試圖在眼睛狀態歷史中找到closed-open-closed模式。
3.活體人臉識別
我們幾乎具備了建立人臉識別算法的所有要素。我們只需要一種實時檢測人臉和眼睛的方法。我使用openCV預訓練的Haar-cascade分類器來完成這些任務
上述函數是用於檢測和識別真實面部的Python代碼。它需要的參數:model:我們的open/closed眼睛分類器video_capture:流視頻face_detector:Haar-cascade face分類器。使用haarcascade_frontalface_alt.xmlopen_eyes_detector:Haar-cascade 睜眼的 分類器。使用haarcascade_eye_tree_eyeglasses.xmlleft_eye_detector:Haar-cascade左眼分類器。使用haarcascade_lefteye_2splits.xml,它可以檢測睜開或閉上的眼睛。right_eye_detector:Haar-cascade右眼分類器。使用haarcascade_righteye_2splits.xml,它可以檢測睜開或閉上的眼睛。data:已知編碼和已知人名的字典eyes_detected:一個字典,包含每個眼睛狀態歷史記錄。代碼解析:
在第2-4行,我們從webcam流中獲取一個幀,然後調整它的大小以加快計算速度。在第10行,我們從幀中檢測人臉,然後在第21行,我們將其編碼為128-d向量。在第23-38行,我們將這個向量與已知的面部編碼進行比較,並通過計算匹配的數量來確定此人的姓名。選擇匹配數量最大的一個。從第45行開始,我們嘗試將在面部框中進行眼睛檢測。首先,我們嘗試使用open_eye_detector檢測睜眼。如果探測器成功,那麼在第54行, 我們在眼睛狀態歷史中添加「1」,這意味著眼睛是睜著的,因為open_eye_detector無法檢測閉著的眼睛。否則,如果第一個分類器失敗了(可能是因為眼睛是閉著的,或者僅僅是因為它沒有識別眼睛),那麼我們嘗試使用left_eye和right_eye檢測器。為此我們需要將人臉分為左右兩部分,分別提供給每個分類器。從第92行開始,我們提取眼部,我們使用之前訓練的機器學習模型預測眼睛是否閉著。如果我們檢測到一隻眼閉著,我們假設雙眼都閉合了,我們在眼睛狀態歷史中添加「0」。否則我們認為眼睛是睜著的。最後在第110行我們使用isBlinking()用於檢測眨眼的函數,如果此人眨眼,我們會顯示其姓名。4.程序其他部分代碼