1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        僅使用OpenCV實現(xiàn)活體檢測!(附源碼)

        共 7706字,需瀏覽 16分鐘

         ·

        2021-10-30 12:58

        點擊上方小白學視覺”,選擇加"星標"或“置頂

        重磅干貨,第一時間送達

        我們先來看一個網(wǎng)絡留言


        ?來自蝦米媽咪

        小朋友用媽媽的一寸照片通過了人臉識別,打擊了小度音箱的家長監(jiān)督機制。

        活體檢測沒做好。

        公交車身廣告上的董明珠頭像,被寧波交警系統(tǒng)拍了照,判定成“違法闖紅燈”。

        活體檢測沒做好。

        所以,活體檢測要怎么做?

        名叫Adrian Rosebrock的程序猿,寫了份事無巨細的教程,從構建數(shù)據(jù)集開始,一步步教大家用AI分辨真人和照片,精細到每行代碼的用途。

        ?川川是假的,光頭是真的

        這個識別方法,用到了OpenCVKeras,打開攝像頭就可以實時檢測。

        重要的是,有源碼提供,受到了推特用戶的踴躍比心。

        活體檢測,可以檢測些什么?

        AI可以用哪些技巧,來區(qū)分真人和照片?

        一是紋理分析?(Texture Analysis) 。皮膚的紋理特征是重要的依據(jù),給2D照片拍照,比起給3D真人拍照,會損失一些紋理。

        二是頻率分析?(Frequency Analysis) 。照片臉部的頻率組成,也不像真人那樣豐富。

        三是可變聚焦分析?(Variable focusing Analysis) 。連拍兩張照片,聚焦在不同位置,查看像素值 (Pixel Value) 的變化。

        四是啟發(fā)式算法?(Heuristic-Based Algorithms) 。眼動、唇動、眨眼這些動作,照片是不會有的。

        五是光流算法?(Optical Flow Algorithms) 。在相鄰兩幀之間,檢測物體運動的方向和幅度,查出2D和3D物體之間的差別。

        ……

        不過這里,就把活體檢測看成一個粗暴的二分類問題,這些復雜的分析先拋到一邊。

        自制數(shù)據(jù)集


        程序猿把問題又簡化了一下:這里說的“假臉”,只是“屏幕里的人臉”而已。

        現(xiàn)在,可以開始造數(shù)據(jù)集了。

        他用手機的前攝像頭拍了一段25秒的視頻;又舉著手機、對著電腦攝像頭,把視頻播了一遍。

        這樣,一段真人視頻,和一段“假臉”視頻,就準備好了。

        程序猿拍下的這兩條視頻,都提供下載。不過,他還是建議大家多收集一些數(shù)據(jù),不同的人臉,甚至不同的人種,幫助算法茁壯成長。

        下一步,要用OpenCV的人臉檢測算法處理兩段視頻,把有用的區(qū)域 (ROI) ,就是人臉部分框出來。

        這步用了80多行代碼,每一行在做些什么,教程里都寫清了。

        最后,按照真假兩個類別,把框好的臉部提取出來,就有了數(shù)據(jù)集。

        溫馨提示,需要平衡一下真圖和假圖的數(shù)量。比如,程序猿發(fā)現(xiàn)真實視頻比假視頻長,就用更大的間隔來提取。于是,他收獲了真圖161張,假圖150張。

        這數(shù)據(jù)集還是顯得有些貧乏,所以后面需要擴增:旋轉(zhuǎn)、翻轉(zhuǎn)之類的操作,可以增加圖片數(shù)量。

        活體檢測模型


        數(shù)據(jù)集做好了,就要喂給做活體檢測的神經(jīng)網(wǎng)絡。

        程序猿給網(wǎng)絡起名LivenessNet,大體長這樣:

        他說,這其實只是一個簡單的CNN。而且,已經(jīng)努力讓網(wǎng)絡保持在最淺、參數(shù)最少的狀態(tài)。

        這樣做有兩個原因:一是為避免模型在小數(shù)據(jù)集上發(fā)生過擬合,二是為保證模型快到可以實時推理,就算在樹莓派上也能運行。

        搭個網(wǎng)絡

        現(xiàn)在,就來實現(xiàn)一下這個網(wǎng)絡。打開livenessnet.py,再寫這一段代碼:

         1#?import?the?necessary?packages
        2from?keras.models?import?Sequential
        3from?keras.layers.normalization?import?BatchNormalization
        4from?keras.layers.convolutional?import?Conv2D
        5from?keras.layers.convolutional?import?MaxPooling2D
        6from?keras.layers.core?import?Activation
        7from?keras.layers.core?import?Flatten
        8from?keras.layers.core?import?Dropout
        9from?keras.layers.core?import?Dense
        10from?keras?import?backend?as?K
        11
        12class?LivenessNet:
        13????@staticmethod
        14????def?build(width,?height,?depth,?classes):
        15????????#?initialize?the?model?along?with?the?input?shape?to?be
        16????????#?"channels?last"?and?the?channels?dimension?itself
        17????????model?=?Sequential()
        18????????inputShape?=?(height,?width,?depth)
        19????????chanDim?=?-1
        20
        21????????#?if?we?are?using?"channels?first",?update?the?input?shape
        22????????#?and?channels?dimension
        23????????if?K.image_data_format()?==?"channels_first":
        24????????????inputShape?=?(depth,?height,?width)
        25????????????chanDim?=?1

        然后,一層一層加上去:

         1????????#?first?CONV?=>?RELU?=>?CONV?=>?RELU?=>?POOL?layer?set
        2????????model.add(Conv2D(16,?(3,?3),?padding="same",
        3????????????input_shape=inputShape))
        4????????model.add(Activation("relu"))
        5????????model.add(BatchNormalization(axis=chanDim))
        6????????model.add(Conv2D(16,?(3,?3),?padding="same"))
        7????????model.add(Activation("relu"))
        8????????model.add(BatchNormalization(axis=chanDim))
        9????????model.add(MaxPooling2D(pool_size=(2,?2)))
        10????????model.add(Dropout(0.25))
        11
        12????????#?second?CONV?=>?RELU?=>?CONV?=>?RELU?=>?POOL?layer?set
        13????????model.add(Conv2D(32,?(3,?3),?padding="same"))
        14????????model.add(Activation("relu"))
        15????????model.add(BatchNormalization(axis=chanDim))
        16????????model.add(Conv2D(32,?(3,?3),?padding="same"))
        17????????model.add(Activation("relu"))
        18????????model.add(BatchNormalization(axis=chanDim))
        19????????model.add(MaxPooling2D(pool_size=(2,?2)))
        20????????model.add(Dropout(0.25))

        程序猿說,這個網(wǎng)絡有點像VGGNet,很淺,過濾器 (Filter) 很少。只是判斷真假,不用深度網(wǎng)絡。

        最后,再加一個FC層→RELU層的組合。

         1????????#?first?(and?only)?set?of?FC?=>?RELU?layers
        2????????model.add(Flatten())
        3????????model.add(Dense(64))
        4????????model.add(Activation("relu"))
        5????????model.add(BatchNormalization())
        6????????model.add(Dropout(0.5))
        7
        8????????#?softmax?classifier
        9????????model.add(Dense(classes))
        10????????model.add(Activation("softmax"))
        11
        12????????#?return?the?constructed?network?architecture
        13????????return?model

        CNN搭好了,該訓練了。

        訓練腳本長這樣

        大致的訓練過程,就像這張圖:

        打開train_liveness.py,寫下這段代碼:

        1#?set?the?matplotlib?backend?so?figures?can?be?saved?in?the?background
        2import?matplotlib
        3matplotlib.use("Agg")
        4
        5#?import?the?necessary?packages
        6from?pyimagesearch.livenessnet?import?LivenessNet
        7from?sklearn.preprocessing?import?LabelEncoder
        8from?sklearn.model_selection?import?train_test_split
        9from?sklearn.metrics?import?classification_report
        10from?keras.preprocessing.image?import?ImageDataGenerator
        11from?keras.optimizers?import?Adam
        12from?keras.utils?import?np_utils
        13from?imutils?import?paths
        14import?matplotlib.pyplot?as?plt
        15import?numpy?as?np
        16import?argparse
        17import?pickle
        18import?cv2
        19import?os
        20
        21#?construct?the?argument?parser?and?parse?the?arguments
        22ap?=?argparse.ArgumentParser()
        23ap.add_argument("-d",?"--dataset",?required=True,
        24????help="path?to?input?dataset")
        25ap.add_argument("-m",?"--model",?type=str,?required=True,
        26????help="path?to?trained?model")
        27ap.add_argument("-l",?"--le",?type=str,?required=True,
        28????help="path?to?label?encoder")
        29ap.add_argument("-p",?"--plot",?type=str,?default="plot.png",
        30????help="path?to?output?loss/accuracy?plot")
        31args?=?vars(ap.parse_args())

        ?導入,不停地導入

        里面包含了許多的導入

        matplotlib,是可視化工具;

        LivenessNet,就是剛才搭好的CNN;

        train_test_split,這是scikit-learn里的函數(shù),把數(shù)據(jù)集拆成訓練集和測試集;

        classification_report,也是scikit-learn里面的工具,用來生成簡短統(tǒng)計報告的;

        ImageDataGenerator,做數(shù)據(jù)擴增用的;

        Adam,適合這個任務的優(yōu)化器,當然也可以用SGD、RMSprop等等代替;

        paths,這個模塊是用來收集圖片路徑的;

        pyplot,也是美麗的可視化工具;

        numpy,是Python數(shù)學庫,也是OpenCV必需品;

        argparse,用來處理命令行參數(shù);

        pickle,可以把標簽編碼器序列化到盤上;

        cv2,這是一組OpenCV Binding;

        還有os,這個模塊用處很多,但這里只用到了它的操作系統(tǒng)路徑分隔符而已。

        梳理好這些,再看余下的代碼,就會清晰很多了。

        后面,是一系列的初始化,以及訓練前的各種準備活動。此處略去,詳見教程原文。

        訓練正式啟動

        準備就緒,運行這段命令,就可以訓練了:

         1$?python?train.py?--dataset?dataset?--model?liveness.model?--le?le.pickle
        2[INFO]?loading?images...
        3[INFO]?compiling?model...
        4[INFO]?training?network?for?50?epochs...
        5Epoch?1/50
        629/29?[==============================]?-?2s?58ms/step?-?loss:?1.0113?-?acc:?0.5862?-?val_loss:?0.4749?-?val_acc:?0.7436
        7Epoch?2/50
        829/29?[==============================]?-?1s?21ms/step?-?loss:?0.9418?-?acc:?0.6127?-?val_loss:?0.4436?-?val_acc:?0.7949
        9Epoch?3/50
        1029/29?[==============================]?-?1s?21ms/step?-?loss:?0.8926?-?acc:?0.6472?-?val_loss:?0.3837?-?val_acc:?0.8077
        11...
        12Epoch?48/50
        1329/29?[==============================]?-?1s?21ms/step?-?loss:?0.2796?-?acc:?0.9094?-?val_loss:?0.0299?-?val_acc:?1.0000
        14Epoch?49/50
        1529/29?[==============================]?-?1s?21ms/step?-?loss:?0.3733?-?acc:?0.8792?-?val_loss:?0.0346?-?val_acc:?0.9872
        16Epoch?50/50
        1729/29?[==============================]?-?1s?21ms/step?-?loss:?0.2660?-?acc:?0.9008?-?val_loss:?0.0322?-?val_acc:?0.9872
        18[INFO]?evaluating?network...
        19??????????????precision????recall??f1-score???support
        20
        21????????fake???????0.97??????1.00??????0.99????????35
        22????????real???????1.00??????0.98??????0.99????????43
        23
        24???micro?avg???????0.99??????0.99??????0.99????????78
        25???macro?avg???????0.99??????0.99??????0.99????????78
        26weighted?avg???????0.99??????0.99??????0.99????????78
        27
        28[INFO]?serializing?network?to?'liveness.model'...

        成果斐然

        訓練完結,LivenessNet在驗證集上拿到了99%的準確度。

        當然,驗證集只是熱身,后面還要打開攝像頭,讓AI去看更多沒見過的人,和沒見過的“假人”。

        (這一部分代碼,也有詳盡的解讀,參見教程原文。)

        就像開頭展示的那樣,AI能清楚地判斷,它眼前的川川不是真人,而程序猿是真人。

        那么,你也可以訓練一只這樣的AI了。

        不過,不用局限于簡單的二分類,可以用上前面講到的那些復雜的分析方法,比如頻率分析,比如光流法,大有可為。

        教程原文傳送門:
        https://www.pyimagesearch.com/2019/03/11/liveness-detection-with-opencv/

        源碼下載入口,和無微不至的代碼解析,都在里面了。


        下載1:OpenCV-Contrib擴展模塊中文版教程
        在「小白學視覺」公眾號后臺回復:擴展模塊中文教程,即可下載全網(wǎng)第一份OpenCV擴展模塊教程中文版,涵蓋擴展模塊安裝、SFM算法、立體視覺、目標跟蹤、生物視覺、超分辨率處理等二十多章內(nèi)容。

        下載2:Python視覺實戰(zhàn)項目52講
        小白學視覺公眾號后臺回復:Python視覺實戰(zhàn)項目,即可下載包括圖像分割、口罩檢測、車道線檢測、車輛計數(shù)、添加眼線、車牌識別、字符識別、情緒檢測、文本內(nèi)容提取、面部識別等31個視覺實戰(zhàn)項目,助力快速學校計算機視覺。

        下載3:OpenCV實戰(zhàn)項目20講
        小白學視覺公眾號后臺回復:OpenCV實戰(zhàn)項目20講,即可下載含有20個基于OpenCV實現(xiàn)20個實戰(zhàn)項目,實現(xiàn)OpenCV學習進階。

        交流群


        歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動駕駛、計算攝影、檢測、分割、識別、醫(yī)學影像、GAN算法競賽等微信群(以后會逐漸細分),請掃描下面微信號加群,備注:”昵稱+學校/公司+研究方向“,例如:”張三?+?上海交大?+?視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進入相關微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~


        瀏覽 61
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            在线观看免费无码视频 | 亚洲AV成人无码18禁在线 | 99色在线| 日本护士囗交吞精 | 开宫灌浓精h怀孕 | 黄色床上搞鸡网站 | 欧美成人无码呻吟猛交XX性 | 日韩一区二区三区四区中文在线 | 三级黄片免费看 | 国产精品成人无码免费视频小说 |