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

        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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/619195.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【CSP CCF记录】数组推导

题目 过程 思路 每次输入一个Bi即可确定一个Ai值&#xff0c;用temp记录1~B[i-1]&#xff0c;的最大值分为两种情况&#xff1a; 当temp不等于Bi时&#xff0c;则说明Bi值之前未出现过&#xff0c;Ai必须等于Bi才能满足Bi是Ai前缀最大的定义。当temp等于Bi时&#xff0c;则说…

后端开发之用Mybatis简化JDBC的开发快速入门2024及数据库连接池技术和lombok工具详解

JDBC 简化JDBC的开发 JDBC仅仅是一套接口 是一套规范 Mybatis是持久层框架 用于简化JDBC的开发 使用Java语言操作关系型数据库的一套API 原始的JDBC程序 package com.bigdate.mybatis;import com.bigdate.mybatis.mapper.UserMapper; import com.bigdate.mybatis.pojo.Use…

(二)Jetpack Compose 布局模型

前文回顾 &#xff08;一&#xff09;Jetpack Compose 从入门到会写-CSDN博客 首先让我们回顾一下上一篇文章中里提到过几个问题&#xff1a; ComposeView的层级关系&#xff0c;互相嵌套存在的问题&#xff1f; 为什么Compose可以实现只测量一次&#xff1f; ComposeView和…

【JVM】感觉弗如...类加载机制

【JVM】感觉弗如…类加载机制 在Java开发过程中&#xff0c;从源代码&#xff08;.java文件&#xff09;到字节码&#xff08;.class文件&#xff09;再到运行时的类加载&#xff0c;会经历几个关键步骤&#xff0c;我们先简单过一遍大体的过程。再介绍今天这篇博客的重点内容—…

几个字符串函数的使用和模拟实现(2)

strcop的使用和模拟实现 strcpy函数的使用事项&#xff1a; 源字符串时不需要修改的&#xff0c;在定义前加上const 源字符串被拷贝到目标字符串上时终止字符\0也被拷贝进去 目标数组的大小要相对于源数组的大小足够大&#xff0c;并且不应该在内存中重叠 函数的返回值是一个字…

【Unity】Unity项目转抖音小游戏(二)云数据库和云函数

业务需求&#xff0c;开始接触一下抖音小游戏相关的内容&#xff0c;开发过程中记录一下流程。 抖音云官方文档&#xff1a;https://developer.open-douyin.com/docs/resource/zh-CN/developer/tools/cloud/develop-guide/cloud-function-debug 1.开通抖音云环境 抖音云地址&a…

软件体系结构风格

目录 一、定义 二、.经典软件体系结构风格&#xff1a; 1.管道和过滤器 2.数据抽象和面向对象系统 3.基于事件系统&#xff08;隐式调用&#xff09; 4.分层系统 5.仓库 6.C2风格 7.C/S 8.三层C/S 9.B/S 题&#xff1a; 一、定义 软件体系机构风格是描述某一特定应用…

C#泛型委托

在C#中&#xff0c;delegate 关键字用于声明委托&#xff08;delegates&#xff09;&#xff0c;委托是一种类型安全的函数指针&#xff0c;允许你传递方法作为参数或从方法返回方法。有时我们需要将一个函数作为另一个函数的参数&#xff0c;这时就要用到委托&#xff08;Dele…

java项目之车辆管理系统(springboot+vue+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的车辆管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 车辆管理系统的主要使用者分…

Deckset for Mac:让演示文稿制作更轻松

还在为繁琐的演示文稿制作而烦恼吗&#xff1f;Deckset for Mac来帮您解决&#xff01;它支持Markdown语言&#xff0c;让您只需专注于内容的创作&#xff0c;无需在排版和设计上耗费过多精力。丰富的主题和布局选项&#xff0c;让您能够轻松打造出专业级的演示文稿。快来体验D…

云计算第十二课

安装虚拟机 第一步新建虚拟机 选择自定义安装 下一步 选择稍后安装操作系统 选择系统类型和版本 选择虚拟机文件路径&#xff08;建议每台虚拟机单独存放并且路径不要有中文&#xff09;点击下一步 选择bios下一步 选择虚拟机处理器内核数量 默认硬盘或者自行调大硬盘 选择虚…

软件测试的分类

1.用户分类 2.查看代码分类 3.阶段分类

云计算十三课

centos安装 点击左上角文件 点击新建虚拟机 点击下一步 点击稍后安装操作系统&#xff0c;下一步 选择Linux&#xff08;l&#xff09;下一步 设置虚拟机名称 点击浏览选择安装位置 新建文件夹设置名称不能为中文&#xff0c;点击确定 点击下一步 设置磁盘大小点击下一步…

4.1 编写程序,从键盘接收一个小写字母,然后找出他的前导字符和后续字符,再按顺序显示这三个字符

方法一&#xff1a; 运行效果&#xff1a; 输入B&#xff0c;输出显示ABC&#xff1b;输入A&#xff0c;输出显示AB 思路&#xff1a; 1、通过键盘输入接收一个字母。 2、将输入的字母减去1&#xff0c;得到前导字符&#xff0c;然后输出。 3、将输入的字母加上1&#xff0c;得…

【python量化交易】qteasy使用教程07——创建更加复杂的自定义交易策略

创建更加复杂的自定义交易策略 使用交易策略类&#xff0c;创建更复杂的自定义策略开始前的准备工作本节的目标继承Strategy类&#xff0c;创建一个复杂的多因子选股策略策略和回测参数配置&#xff0c;并开始回测 本节回顾 使用交易策略类&#xff0c;创建更复杂的自定义策略 …

(四十)第 6 章 树和二叉树(树的双亲表存储)

1. 背景说明 2. 示例代码 1) errorRecord.h // 记录错误宏定义头文件#ifndef ERROR_RECORD_H #define ERROR_RECORD_H#include <stdio.h> #include <string.h> #include <stdint.h>// 从文件路径中提取文件名 #define FILE_NAME(X) strrchr(X, \\) ? strrch…

基于yolov5+streamlit目标检测演示系统设计

YOLOv5与Streamlit&#xff1a;智能目标检测可视化展示介绍 随着人工智能技术的飞速发展&#xff0c;目标检测技术已成为推动智能化社会进步的关键技术之一。在众多目标检测算法中&#xff0c;YOLOv5以其卓越的性能和实时性&#xff0c;成为了业界的佼佼者。与此同时&#xff…

代码随想录阅读笔记-动态规划【爬楼梯】

题目 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 注意&#xff1a;给定 n 是一个正整数。 示例 1&#xff1a; 输入&#xff1a; 2输出&#xff1a; 2解释&#xff1a; 有两种方法可以爬到楼…

[AutoSar]BSW_Diagnostic_002 DCM模块介绍

目录 关键词平台说明背景一、DCM所处架构位置二、DCM 与其他模块的交互三、DCM 的功能四、DCM的内部子模块4.1 Diagnostic Session Layer (DSL)4.1 DSL 与其他模块的交互 4.2 Diagnostic Service Dispatcher (DSD)4.3 Diagnostic Service Processing (DSP)4.4 小结 关键词 嵌入…

vue3土味情话pinia可以持久保存再次修改App样式

我是不是你最疼爱的人-失去爱的城市 <template><div class"talk"><button click"getLoveTalk">土味情话</button><ul><li v-for"talk in talkStore.talkList" :key"talk.id">{{ talk.title }}<…