照片解鎖手機不能忍?教你用OpenCV做活體檢測
圓栗子 編譯整理
量子位 出品 | 公眾號 QbitAI
來自蝦米媽咪
小朋友用媽媽的一寸照片通過了人臉識別,打擊了小度音箱的家長監督機制。
活體檢測沒做好。
公交車身廣告上的董明珠頭像,被寧波交警系統拍了照,判定成「違法闖紅燈」。
活體檢測沒做好。
所以,活體檢測要怎麼做?
名叫Adrian Rosebrock的程序猿,寫了份事無巨細的教程,從構建數據集開始,一步步教大家用AI分辨真人和照片,精細到每行代碼的用途。
川川是假的,光頭是真的
這個識別方法,用到了OpenCV和Keras,打開攝像頭就可以實時檢測。
重要的是,有源碼提供,受到了推特用戶的踴躍比心。
活體檢測,可以檢測些什麼?
AI可以用哪些技巧,來區分真人和照片?
一是紋理分析(Texture Analysis) 。皮膚的紋理特徵是重要的依據,給2D照片拍照,比起給3D真人拍照,會損失一些紋理。
二是頻率分析(Frequency Analysis) 。照片臉部的頻率組成,也不像真人那樣豐富。
三是可變聚焦分析(Variable focusing Analysis) 。連拍兩張照片,聚焦在不同位置,查看像素值 (Pixel Value) 的變化。
四是啟發式演算法(Heuristic-Based Algorithms) 。眼動、唇動、眨眼這些動作,照片是不會有的。
五是光流演算法(Optical Flow Algorithms) 。在相鄰兩幀之間,檢測物體運動的方向和幅度,查出2D和3D物體之間的差別。
……
不過這裡,就把活體檢測看成一個粗暴的二分類問題,這些複雜的分析先拋到一邊。
自製數據集
程序猿把問題又簡化了一下:這裡說的「假臉」,只是「屏幕里的人臉」而已。
現在,可以開始造數據集了。
他用手機的前攝像頭拍了一段25秒的視頻;又舉著手機、對著電腦攝像頭,把視頻播了一遍。
這樣,一段真人視頻,和一段「假臉」視頻,就準備好了。
程序猿拍下的這兩條視頻,都提供下載。不過,他還是建議大家多收集一些數據,不同的人臉,甚至不同的人種,幫助演算法茁壯成長。
下一步,要用OpenCV的人臉檢測演算法處理兩段視頻,把有用的區域 (ROI) ,就是人臉部分框出來。
這步用了80多行代碼,每一行在做些什麼,教程里都寫清了。
最後,按照真假兩個類別,把框好的臉部提取出來,就有了數據集。
溫馨提示,需要平衡一下真圖和假圖的數量。比如,程序猿發現真實視頻比假視頻長,就用更大的間隔來提取。於是,他收穫了真圖161張,假圖150張。
這數據集還是顯得有些貧乏,所以後面需要擴增:旋轉、翻轉之類的操作,可以增加圖片數量。
活體檢測模型
數據集做好了,就要餵給做活體檢測的神經網路。
程序猿給網路起名LivenessNet,大體長這樣:
他說,這其實只是一個簡單的CNN。而且,已經努力讓網路保持在最淺、參數最少的狀態。
這樣做有兩個原因:一是為避免模型在小數據集上發生過擬合,二是為保證模型快到可以實時推理,就算在樹莓派上也能運行。
搭個網路
現在,就來實現一下這個網路。打開livenessnet.py,再寫這一段代碼:
然後,一層一層加上去:
程序猿說,這個網路有點像VGGNet,很淺,過濾器 (Filter) 很少。只是判斷真假,不用深度網路。
最後,再加一個FC層RELU層的組合。
CNN搭好了,該訓練了。
訓練腳本長這樣
大致的訓練過程,就像這張圖:
打開train_liveness.py,寫下這段代碼:
1# set the matplotlib backend so figures can be saved in the background
2importmatplotlib
3matplotlib.use("Agg")
4
5# import the necessary packages
6frompyimagesearch.livenessnetimportLivenessNet
7fromsklearn.preprocessingimportLabelEncoder
8fromsklearn.model_selectionimporttrain_test_split
9fromsklearn.metricsimportclassification_report
10fromkeras.preprocessing.imageimportImageDataGenerator
11fromkeras.optimizersimportAdam
12fromkeras.utilsimportnp_utils
13fromimutilsimportpaths
14importmatplotlib.pyplotasplt
15importnumpyasnp
16importargparse
17importpickle
18importcv2
19importos
20
21# construct the argument parser and parse the arguments
22ap = argparse.ArgumentParser()
23ap.add_argument("-d","--dataset", required=True,
24help="path to input dataset")
25ap.add_argument("-m","--model", type=str, required=True,
26help="path to trained model")
27ap.add_argument("-l","--le", type=str, required=True,
28help="path to label encoder")
29ap.add_argument("-p","--plot", type=str, default="plot.png",
30help="path to output loss/accuracy plot")
31args = vars(ap.parse_args())
導入,不停地導入
裡面包含了許多的導入:
有matplotlib,是可視化工具;
有LivenessNet,就是剛才搭好的CNN;
有train_test_split,這是scikit-learn里的函數,把數據集拆成訓練集和測試集;
有classification_report,也是scikit-learn裡面的工具,用來生成簡短統計報告的;
有ImageDataGenerator,做數據擴增用的;
有Adam,適合這個任務的優化器,當然也可以用SGD、RMSprop等等代替;
有paths,這個模塊是用來收集圖片路徑的;
有pyplot,也是美麗的可視化工具;
有numpy,是Python數學庫,也是OpenCV必需品;
有argparse,用來處理命令行參數;
有pickle,可以把標籤編碼器序列化到盤上;
有cv2,這是一組OpenCV Binding;
還有os,這個模塊用處很多,但這裡只用到了它的操作系統路徑分隔符而已。
梳理好這些,再看餘下的代碼,就會清晰很多了。
後面,是一系列的初始化,以及訓練前的各種準備活動。此處略去,詳見教程原文。
訓練正式啟動
準備就緒,運行這段命令,就可以訓練了:
成果斐然
訓練完結,LivenessNet在驗證集上拿到了99%的準確度。
當然,驗證集只是熱身,後面還要打開攝像頭,讓AI去看更多沒見過的人,和沒見過的「假人」。
(這一部分代碼,也有詳盡的解讀,參見教程原文。)
就像開頭展示的那樣,AI能清楚地判斷,它眼前的川川不是真人,而程序猿是真人。
那麼,你也可以訓練一隻這樣的AI了。
不過,不用局限於簡單的二分類,可以用上前面講到的那些複雜的分析方法,比如頻率分析,比如光流法,大有可為。
教程原文傳送門:
https://www.pyimagesearch.com/2019/03/11/liveness-detection-with-opencv/
源碼下載入口,和無微不至的代碼解析,都在裡面了。
—
完—
訂閱AI內參,獲取AI行業資訊
購買AI書籍
誠摯招聘
量子位正在招募編輯/記者,工作地點在北京中關村。期待有才氣、有熱情的同學加入我們!相關細節,請在量子位公眾號(QbitAI)對話界面,回復「招聘」兩個字。
喜歡就點「好看」吧 !
※吳恩達有套路:試點項目、內外PR、取信CEO……AI轉型,如何得人心?
※圍棋AI ELF OpenGo全面開源,田淵棟揭秘訓練過程
TAG:量子位 |