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

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐