问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

SeetaFace6人脸活体检测C++代码实现Demo

创作时间:
作者:
@小白创作中心

SeetaFace6人脸活体检测C++代码实现Demo

引用
CSDN
1.
https://blog.csdn.net/mickey2007/article/details/138243986

SeetaFace6 是一个功能强大的人脸识别系统,除了基本的人脸检测、关键点定位和人脸识别能力外,还提供了活体检测、质量评估、年龄性别估计等功能。本文将详细介绍 SeetaFace6 的人脸活体检测功能,包括其原理、使用方法和参数设置,并通过实际的代码示例和演示效果帮助读者快速上手。

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

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号