SeetaFace6人脸特征提取与对比C++代码实现Demo

        SeetaFace6包含人脸识别的基本能力:人脸检测、关键点定位、人脸识别,同时增加了活体检测、质量评估、年龄性别估计,并且顺应实际应用需求,开放口罩检测以及口罩佩戴场景下的人脸识别模型。

        官网地址:https://github.com/SeetaFace6Open/index

1. 概述

        人脸特征提取与对比,就是将待识别的人脸经过处理变成二进制数据的特征,然后基于特征表示的人脸进行相似度计算,最终与相似度阈值对比,一般超过阈值就认为特征表示的人脸是同一个人。

        为了应对不同级别的应用需求,SeetaFace6将开放三个版本模型:

文件名

特征长度

建议阈值

说明

face_recognizer.csta

1024

0.62

通用场景高精度人脸识别

face_recognizer_mask.csta

512

0.48

带口罩人脸识别模型

face_recognizer_light.csta

512

0.55

轻量级人脸识别模型

        需要注意的是,不同模型提取的特征是不具备可比较性的,哪怕特征一样。如果在正在运行的系统替换了识别模型的话,所有底库照片全部需要重新提取特征再进行比较才行。

2. 人脸特征提取

        首先构造人脸识别器:

#include <seeta/FaceRecognizer.h>
seeta::FaceRecognizer *new_fr() {seeta::ModelSetting setting;setting.append("face_recognizer.csta");return new seeta::FaceRecognizer(setting);
}

        特征提取过程可以分为两个步骤:

  1. 根据人脸5个关键点裁剪出人脸区域
  2. 人脸区域输入特征提取网络提取特征。

        两个步骤分别对应seeta::FaceRecognizerCropFaceV2ExtractCroppedFace

        特征长度是不同模型可能不同的,要使用GetExtractFeatureSize方法获取当前使用模型提取的特征长度。

#include <seeta/FaceRecognizer.h>
#include <memory>
std::shared_ptr<float> extract_v2(seeta::FaceRecognizer *fr,const SeetaImageData &image,const std::vector<SeetaPointF> &points) 
{std::shared_ptr<float> features(new float[fr->GetExtractFeatureSize()],std::default_delete<float[]>());seeta::ImageData face = fr->CropFaceV2(image, points.data());fr->ExtractCroppedFace(face, features.get());return features;
}

3. 人脸特征对比

        人脸特征对比就是计算两个特征的相似度,相似度的范围是[0, 1]

#include <seeta/FaceRecognizer.h>
#include <memory>float compare(seeta::FaceRecognizer *fr,const std::shared_ptr<float> &feat1,const std::shared_ptr<float> &feat2) 
{return fr->CalculateSimilarity(feat1.get(), feat2.get());
}

4. 关于相似度和阈值

        阈值起到的作用就是给出识别结果是否是同一个人的评判标准。如果两个特征的相似度超过阈值,则认为两个特征所代表的人脸就是同一个人。

        因此该阈值和对应判断的相似度,是算法统计是否一个人的评判标准,并不等同于自然语义下的人脸的相似度。这样表述可能比较抽象,说个具体的例子就是,相似度0.5,在阈值是0.49的时候,就表示识别结果就是一个人,这个相似度也不表示两个人脸有一半长的一样。同理相似度100%,也不表示两个人脸完全一样,连岁月的痕迹也没有留下。

        识别算法直接给出来的相似度如果脱离阈值就没有意义。识别算法的性能好不好,主要看其给出的不同样本之间的相似度有没有区分性,能够用阈值将正例和负例样本区分开来。

        这里对一种错误的测试方式给出说明。经常有人提出问题,A算法比B算法效果差,原因是拿两张照片,是同一个人,A算法给出的相似度比B算法给出的低。但是经过上述讨论,希望读者能够明白这种精度测试方式的片面性。

5. 关于1比1和1比N

        一般的人脸识别应用,我们都可以这样去区分,1比1和1比N。

        一般的1比1识别,狭义上讲就是人证对比,使用读卡器从身份证,或者其他介质上读取到一张照片,然后和现场抓拍到的照片做对比。这种一般是做认证的场景,用来判别证件、或者其他凭证方式是否是本人在进行操作。因此广义上来讲,员工刷工卡,然后刷脸认证;个人账户进行刷脸代替密码;这种知道待识别人员身份,然后进行现场认证的方式,都可以属于1比1识别的范畴。一般的1比1识别,狭义上讲就是人证对比,使用读卡器从身份证,或者其他介质上读取到一张照片,然后和现场抓拍到的照片做对比。这种一般是做认证的场景,用来判别证件、或者其他凭证方式是否是本人在进行操作。因此广义上来讲,员工刷工卡,然后刷脸认证;个人账户进行刷脸代替密码;这种知道待识别人员身份,然后进行现场认证的方式,都可以属于1比1识别的范畴。

        1比N识别与1比1区别在于,对于现场待识别的人脸,不知道其身份,需要在一个底库中去查询,如果在底库中给出对应识别结果,如果不在底库中,报告未识别。

        1比N识别从接口调用上来说,首先需要将底库中的人脸全部提取特征,然后,对现场抓拍到的待识别人脸提取特征,最终使用特征与底库中的特征进行比较选出相似度最高的人脸,这时相似度若超过阈值,则认为识别成功,反之待识别人员不在底库。而常见的1比N识别就是摄像头下的动态人脸识别。

6. 演示Demo

6.1 开发环境

  •   - Windows 10 Pro x64
  •   - Visual Studio 2015
  •   - Seetaface6
  •   - Sqlite

6.2 功能介绍

        演示程序主界面如下图所示,包括人脸注册、人脸1:1验证、人脸1:N辨识、数据库信息、删除和清空等操作。

        (1)人脸注册

        输入用户ID,读取一张人脸图片,进行人脸检测、特征提取;左侧显示读取的人脸图片,右侧显示注册成功的人脸图片,并保存人脸特征到sqlite数据库。

        (2)人脸1:1验证

        输入用户ID,检测该用户ID是否已注册;如果已注册,读取一张人脸图片,进行人脸检测和特征提取,并与数据库中存储的该ID人脸特征进行比对;比对结果显示左下角,左上显示读取的人脸图片,右下显示已注册的人脸图片。

        (3)人脸1:N辨识

        读取一张人脸图片,进行人脸检测和特征提取,并与数据库中存储的每个人脸特征依次进行比对;比对结果显示左下角,左上显示读取的人脸图片,右下显示已辨识到的人脸图片。

        (4)数据库信息

        单击“数据库信息”,左下角将显示数据库的记录数,以及用户ID。

        (5)删除

        单击“删除”,根据输入用户ID,进行记录删除。

        (6)清空

        单击“清空”,删除数据库中所有记录。

6.3 下载地址

        开发环境:

  • Windows 10 pro x64
  • Visual Studio 2015
  • Seetaface6
  • Sqlite

        下载地址:SeetaFace6人脸特征提取与对比C++代码实现Demo

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

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

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

[算法][差分][延迟相差][leetcode]2960. 统计已测试设备

题目地址&#xff1a; https://leetcode.cn/problems/count-tested-devices-after-test-operations/description/ 解法一&#xff1a;暴力解法 class Solution {public int countTestedDevices(int[] batteryPercentages) {//特殊条件判断if(null batteryPercentages || ba…

Java后端初始化项目(项目模板)

介绍 emmmm&#xff0c;最近看了一些网络资料&#xff0c;也是心血来潮&#xff0c;想自己手工搭建一个java后端的初始化项目模板来简化一下开发&#xff0c;也就发一个模板的具体制作流程&#xff0c;&#xff08;一步一步搭建&#xff0c;从易到难&#xff09; ok&#xff…

Rust的协程机制:原理与简单示例

在现代编程中&#xff0c;协程&#xff08;Coroutine&#xff09;已经成为实现高效并发的重要工具。Rust&#xff0c;作为一种内存安全的系统编程语言&#xff0c;也采用了协程作为其并发模型的一部分。本文将深入探讨Rust协程机制的实现原理&#xff0c;并通过一个简单的示例来…

读天才与算法:人脑与AI的数学思维笔记25_涌现理论

1. 人工智能新闻 1.1. 人工智能新闻报道算法的核心是如何将未经处理的原始数据转换成新闻报道 1.2. 很少有记者为美联社决定使用机器来帮助报道这些新闻持反对意见 1.2.1. 像“Wordsmith”这样的算法&#xff0c;具有自动化的洞察力、科学的叙事能力&#xff0c;现在正被应用…

SpringSecurity安全过滤器工作原理

前面通过三篇文章&#xff0c;从底层代码的角度分析了SpringSecurity的初始化过程。 接下来我们就要具体看一下&#xff0c;Spring Security的安全过滤器初始化、装配好之后&#xff0c;到底是怎么工作的。 还是按图索骥 下面我们简单从底层源码分析一下&#xff0c;请求是怎…

leetcode——反转链表

206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;创建三个指针n1,n2,n3&#xff0c;遍历原链表&#xff0c;通过三者之间的关系将链表反转。下面给出图示&#xff1a; 下面给出题解代码&#xff1a; typedef struct ListNode ListNode; struct List…

【C++】vector的底层原理讲解及其实现

目录 一、认识vector底层结构 二、初始化vector的函数 构造函数拷贝构造赋值构造initializer_list构造迭代器区间构造 三、迭代器 四、数据的访问 五、容量相关的函数 六、关于数据的增删查改操作 一、认识vector底层结构 STL库中实现vector其实是用三个指针来完成的&#x…

C# OpenCvSharp Demo - Mat格式化输出、Mat序列化和反序列化

C# OpenCvSharp Demo - Mat格式化输出、Mat序列化和反序列化 目录 效果 项目 代码 下载 效果 直接输出&#xff1a;Mat [ 3*2*CV_8UC3, IsContinuousTrue, IsSubmatrixFalse, Ptr0x1eb73ef9140, Data0x1eb73ef91c0 ]格式化输出&#xff1a;默认风格[ 91, 2, 79, 179, …

JAVA基础--IO

IO 什么是IO 任何事物提到分类都必须有一个分类的标准&#xff0c;例如人&#xff0c;按照肤色可分为&#xff1a;黄的&#xff0c;白的&#xff0c;黑的&#xff1b;按照性别可分为&#xff1a;男&#xff0c;女&#xff0c;人妖。IO流的常见分类标准是按照*流动方向*和*操作…

AI办公自动化-用kimi批量重命名Word文档

文件夹里面有很多个word文档&#xff0c;标题里面都含有零代码编程&#xff0c;现在想将其替换为AI办公自动化。 在kimichat中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;要完成一个编写Python脚本的任务&#xff0c;具体步骤如下&#xff1a; 打开文件夹&am…

windows使用Docker-Desktop部署lobe-chat

文章目录 window安装docker-desktop下载和启动lobe-chatAI大语言模型的选择lobe-chat设置大模型连接 window安装docker-desktop docker-desktop下载地址 正常安装应用&#xff0c;然后启动应用&#xff0c;注意启动docker引擎 打开右上角的设置&#xff0c;进入Docker Engine设…