????????SeetaFace6包含人臉識別的基本能力:人臉檢測、關鍵點定位、人臉識別,同時增加了活體檢測、質量評估、年齡性別估計,并且順應實際應用需求,開放口罩檢測以及口罩佩戴場景下的人臉識別模型。
????????官網地址:https://github.com/SeetaFace6Open/index
1. 概述
????????活體檢測是判斷人臉圖像是來自真人還是來自攻擊假體(照片、視頻等)的方法。
????????人臉識別系統存在被偽造攻擊的風險。因此需要在人臉識別系統中加入活體檢測,驗證用戶是否為真實活體本人操作,以防止照片、視頻、以及三維模型的入侵,從而幫助用戶甄別欺詐行為,保障用戶的利益。
????????活體檢測分為靜默活體檢測和配合式活體檢測。配合式活體檢測即“張張嘴”、“眨眨眼”、“搖搖頭”之類;多應用于APP刷臉登錄、注冊等。靜默活體檢測是不需要任何動作配合,通過算法和攝像頭的配合,進行活體判定;使用起來非常方便,用戶在無感的情況下就可以通過檢測比對,效率非常高。
????《GB∕T 41772-2022 信息技術 生物特征識別 人臉識別系統技術要求》給出了假體攻擊類型包括不限于二維假體攻擊和三維假體攻擊,如下表所示。
二維假體攻擊 | 二維靜態紙張圖像攻擊 | 樣本材質 | 打印紙、亞光相紙、高光相紙、絨面相紙、啞粉紙、銅版紙等 |
樣本質量 | 分辨率、清晰度、大小、角度、光照條件、完整度等 | ||
呈現方式 | 距離、角度、移動、彎曲、折疊等 | ||
裁剪方式 | 圖像是否扣除眼部、鼻子、嘴巴等 | ||
二維靜態電子圖像攻擊 | 設備類型 | 移動終端、微型計算機等 | |
設備顯示性能 | 分辨率、亮度、對比度等 | ||
樣本質量 | 分辨率、清晰度、大小、角度、光照條件、完整度等 | ||
呈現方式 | 距離、角度、移動等 | ||
二維動態圖像攻擊 | 圖像類型 | 錄制視頻、合成視頻等 | |
設備類型 | 移動終端、微型計算機等 | ||
設備顯示性能 | 分辨率、亮度、對比度等 | ||
圖像質量 | 分辨率、清晰度、幀率等 | ||
呈現方式 | 距離、角度、移動等 | ||
三維假體攻擊 | 三維面具攻擊 | 面具材質 | 塑料面具、三維紙張面具、硅膠面具等 |
呈現方式 | 距離、角度、移動等 | ||
光線條件 | 正常光、強光、弱光、逆光等 | ||
裁剪方式 | 面具是否扣除眼部、鼻子、嘴巴等 | ||
三維頭模攻擊 | 頭模材質 | 泡沫、樹脂、全彩砂巖、石英砂等 | |
呈現方式 | 距離、角度、移動等 | ||
光線條件 | 正常光、強光、弱光、逆光等 |
2. SeetaFace6活體檢測
????????SeetaFace6的活體檢測方案,提供了全局活體檢測和局部活體檢測 兩個方法。
- 全局活體檢測就是對圖片整體做檢測,主要是判斷是否出現了活體檢測潛在的攻擊介質,如手機、平板、照片等等。
- 局部活體檢測是對具體人臉的成像細節通過算法分析,區別是一次成像和二次成像,如果是二次成像則認為是出現了攻擊。
2.1 基本使用
????????活體檢測識別器可以加載一個局部檢測模型或者局部檢測模型+全局檢測模型。
????????只加載一個局部檢測模型:
#include <seeta/FaceAntiSpoofing.h>
seeta::FaceAntiSpoofing *new_fas() {seeta::ModelSetting setting;setting.append("fas_first.csta");return new seeta::FaceAntiSpoofing(setting);
}
????????或者局部檢測模型+全局檢測模型,啟用全局檢測能力:
#include <seeta/FaceAntiSpoofing.h>
seeta::FaceAntiSpoofing *new_fas_v2() {seeta::ModelSetting setting;setting.append("fas_first.csta");setting.append("fas_second.csta");return new seeta::FaceAntiSpoofing(setting);
}
????????調用有兩種模式,一個是單幀識別,另外就是視頻識別。 其接口聲明分別為:
seeta::FaceAntiSpoofing::Status seeta::FaceAntiSpoofing::Predict( const SeetaImageData &image, const SeetaRect &face, const SeetaPointF *points ) const;
seeta::FaceAntiSpoofing::Status seeta::FaceAntiSpoofing::PredictVideo( const SeetaImageData &image, const SeetaRect &face, const SeetaPointF *points ) const;
????????從接口上兩者的入參和出參的形式是一樣的。出參這里列一下它的聲明:
class FaceAntiSpoofing {
public:/* * 活體識別狀態 */enum Status{REAL = 0, ///< 真實人臉SPOOF = 1, ///< 攻擊人臉(假人臉)FUZZY = 2, ///< 無法判斷(人臉成像質量不好)DETECTING = 3, ///< 正在檢測};
}
????????單幀識別返回值會是REAL、SPOOF或FUZZY。 視頻識別返回值會是REAL、SPOOF、FUZZY或DETECTING。
????????兩種工作模式的區別在于前者屬于一幀就是可以返回識別結果,而后者要輸入多個視頻幀然后返回識別結果。在視頻識別輸入幀數不滿足需求的時候,返回狀態就是DETECTING。
????????這里給出單幀識別調用的示例:
void predict(seeta::FaceAntiSpoofing *fas, const SeetaImageData &image, const SeetaRect &face, const SeetaPointF *points) {auto status = fas->Predict(image, face, points);switch(status) {case seeta::FaceAntiSpoofing::REAL:std::cout << "真實人臉" << std::endl; break;case seeta::FaceAntiSpoofing::SPOOF:std::cout << "攻擊人臉" << std::endl; break;case seeta::FaceAntiSpoofing::FUZZY:std::cout << "無法判斷" << std::endl; break;case seeta::FaceAntiSpoofing::DETECTING:std::cout << "正在檢測" << std::endl; break;}
}
????????這里需要注意face和points必須對應,也就是points必須是face表示的人臉進行關鍵點定位的結果。points是5個關鍵點。當然image也是需要識別的原圖。
????????如果是視頻識別模式的話,只需要將predict中的fas->Predict(image, face, points)修改為fas->PredictVideo(image, face, points)。
????????在視頻識別模式中,如果該識別結果已經完成,需要開始新的視頻的話,需要調用ResetVideo重置識別狀態,然后重新輸入視頻:
void reset_video(seeta::FaceAntiSpoofing *fas) {fas->ResetVideo();
}
????????當了解基本調用接口之后,就可以直接看出來,識別接口直接輸入的就是單個人臉位置和關鍵點。因此,當視頻或者圖片中存在多張人臉的時候,需要業務決定具體識別哪一個人臉。一般有這幾種選擇,1. 只做單人識別,當出現兩個人的時候識別中止。2. 識別最大的人臉。3. 識別在指定區域中出現的人臉。這幾種選擇對精度本身影響不大,主要是業務選型和使用體驗的區別。
2.2 參數設置
????????設置視頻幀數:
void SetVideoFrameCount( int32_t number );
????????默認為10,當在PredictVideo模式下,輸出幀數超過這個number之后,就可以輸出識別結果。這個數量相當于多幀識別結果融合的融合的幀數。當輸入的幀數超過設定幀數的時候,會采用滑動窗口的方式,返回融合的最近輸入的幀融合的識別結果。一般來說,在10以內,幀數越多,結果越穩定,相對性能越好,但是得到結果的延時越高。
? ? ? ? 設置識別閾值:
void SetThreshold( float clarity, float reality );
????????默認為(0.3, 0.8)。活體識別時,如果清晰度(clarity)低的話,就會直接返回FUZZY。清晰度滿足閾值,則判斷真實度(reality),超過閾值則認為是真人,低于閾值是攻擊。在視頻識別模式下,會計算視頻幀數內的平均值再跟幀數比較。兩個閾值都符合,越高的話,越是嚴格。
????????設置全局檢測閾值:
void SetBoxThresh(float box_thresh);
????????默認為0.8,這個是攻擊介質存在的分數閾值,該閾值越高,表示對攻擊介質的要求越嚴格,一般的疑似就不會認為是攻擊介質。這個一般不進行調整。
????????以上參數設置都存在對應的Getter方法,將方法名稱中的Set改為Get就可以訪問對應的參數獲取了。
2.3 參數調試
????????在應用過程中往往不可避免對閾值產生疑問,如果要調試對應的識別的閾值,這里我們給出了每一幀分數的獲取函數。
????????下面給出識別之后獲取識別具體分數的方法:
void predict_log(seeta::FaceAntiSpoofing *fas, const SeetaImageData &image, const SeetaRect &face, const SeetaPointF *points) {auto status = fas->Predict(image, face, points);float clarity, reality;fas->GetPreFrameScore(&clarity, &reality);std::cout << "clarity = " << clarity << ", reality = " << reality << std::endl;
}
????????在Predict或者PredictVideo之后,調用GetPreFrameScore方法可以獲取剛剛輸入幀的識別分數。
3. 演示Demo
3.1 開發環境
- Windows 10 Pro x64
- Visual Studio 2015
- Seetaface6
3.2 功能介紹
????????演示程序主界面如下圖所示,包括參數顯示、實時活體檢測、取消等功能。
3.3 效果測試
????????二維假體攻擊,包括二維靜態紙張圖像攻擊、二維靜態電子圖像攻擊、二維動態圖像攻擊,檢測效果還是不錯。
????????三維假體攻擊,除了塑料材質檢測效果還可以,其他材質基本無法正確檢測。
3.4 下載地址
????????開發環境:
- Windows 10 pro x64
- Visual Studio 2015
- Seetaface6
? ? ? ? VS工程下載:SeetaFace6人臉活體檢測C++代碼實現Demo