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);
}
特征提取过程可以分为两个步骤:
- 根据人脸5个关键点裁剪出
人脸区域
; - 将
人脸区域
输入特征提取网络提取特征。
两个步骤分别对应seeta::FaceRecognizer
的CropFaceV2
和ExtractCroppedFace
。
特征长度是不同模型可能不同的,要使用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