使用OpenCV内置深度学习人脸模块,几行代码轻松完成人脸检测和识别

作者:冯远滔(OpenCV China),王成瑞(北京邮电大学),钟瑶瑶(北京邮电大学)

最新发布的OpenCV 4.5.4版本收录了一个基于深度学习神经网络的人脸模块(以下称“OpenCV DNN Face”),包括人脸检测(使用模型YuNet,由OpenCV China团队贡献)和人脸识别(使用模型SFace,由北京邮电大学邓伟洪教授课题组贡献)。

使用OpenCV DNN Face的API,只需几行代码便可以完成整个人脸检测和人脸识别处理,极大的方便了开发。

# 人脸检测
img = cv.imread('path/to/image')
faceDetector = cv.FaceDetectorYN.create('/path/to/model', '', img.shape[:2])
faces = faceDetector.detect(image)
# 人脸识别
recognizer = cv.FaceRecognizerSF.create(recog_model_path, '' )
aligned_face = recognizer.alignCrop(img, faces[1][0])
feature = recognizer.feature(aligned_face)
cosine_score = recognizer.match(feature1, feature2, 0)

在相应的数据集上对OpenCV DNN Face的两个模型分别进行测试:

  • 人脸检测模型YuNet在WIDER Face数据集的验证集中达到了0.856(AP_easy),0.842(AP_medium),0.727(AP_hard);

  • 人脸识别模型SFace在LFW数据集上达到了99.60%的准确率 (https://docs.opencv.org/master/d0/dd4/tutorial_dnn_face.html中有更详细的测试结果,以及此人脸模块的一些使用说明)。

根据OpenCV最新公开的OpenCV Zoo(https://github.com/opencv/opencv_zoo)的基准测试结果:

  • 当输入图像尺寸为160x120时,YuNet在i7-5930K@3.50GHz上达到689FPS,在树莓派4B上可达160FPS;

  • SFace在输入图像尺寸为112x112,同样的平台下分别为115FPS和10FPS。

YuNet仅为337K,SFace为37MB,二者均为轻量模型,非常适合移动端应用。

OpenCV DNN Face的实现代码:

https://github.com/opencv/opencv/tree/master/modules/objdetect

C++和Python的例子face_detect和face_match:

https://github.com/opencv/opencv/tree/master/samples/dnn

下面笔者分别介绍一下OpenCV DNN Face中的人脸检测和人脸识别。

OpenCV基于深度学习的人脸检测FaceDetectorYN

人脸检测是返回一张图像中人脸的位置(x1, y1)和大小(w, h),如下图所示(原图片来自于WIDER Face数据集)。

YuNet是广受好评的人脸检测库libfacedetection所使用的模型。它的网络结构设计参考了经典的SSD[1]以及MobileNet[2],其结构示意图可以在

https://netron.app/?url=https://raw.githubusercontent.com/ShiqiYu/libfacedetection.train/master/tasks/task1/onnx/yunet.onnx查看。

YuNet是基于anchor的人脸检测器,分别在4种尺度的特征图上生成正方形anchor,可检测的最小人脸是10x10,最大人脸是256x256。参考MobileNet,我们使用了Depth-wise卷积代替部分卷积,从而减少模型参数和模型体积。我们使用人脸检测数据集WIDER Face[3]作为训练和测试数据集,使用EIoU损失函数[4]作为训练YuNet的损失函数,从而提高对人脸的定位能力。除了人脸的定位之外,我们还额外标注了人脸的5个关键点(左右眼,鼻尖,左右嘴角),为模型增加了关键点检测的多任务能力。

上图展示了FaceDetectorYN的使用流程。如果输入图像的尺寸是一致的,例如视频输入流,那么实例化FaceDetectorYN时指定尺寸(width, height),即可使用detect()方法检测人脸。如果输入图像的尺寸不一致,例如网上搜集的图片,那么实例化FaceDetectorYN时可任意指定尺寸,在使用detect()方法前需要调用setInputSize()方法先指定正确的输入图像尺寸。

C++下人脸检测API(FaceDetectorYN类)的使用方式:

 1// 第一步:导入相关头文件 2#include <opencv2/imgproc.hpp> // cv::imread 3#include <opencv2/objdetect.hpp>  // cv::FaceDetectorYN & cv::FaceRecognizerSF 4using namespace cv; 5 6int main() 7{ 8// 第二步:读取图像 9Mat img = imread('path/to/image');10// 第三步:初始化FaceDetectorYN11Ptr<FaceDetectorYN> faceDetector = FaceDetectorYN::create(modelPath, '', img.size());12// 第四步:检测人脸并将结果保存到一个Mat中13Mat faces;14faceDetector->detect(image, faces);15// faces是一个nx15的二维Mat,每一行分别是:16// [x1, y1, w, h, x_re, y_re, x_le, y_le, x_nt, y_nt, x_rcm, y_rcm, x_lcm, y_lcm, score]17// 其中,x1, y1是人脸框左上角坐标,w和h分别是人脸框的宽和高;{x, y}_{re, le, nt, rcm, lcm}分别是人脸右眼瞳孔、左眼瞳孔、鼻尖、右嘴角和左嘴角的坐标;score是该人脸的得分。18}

Python下人脸检测API的使用方式:

1import numpy as np # 请在import cv2前先import numpy以避免一些问题
2import cv2 as cv
3
4img = cv.imread('path/to/image')
5faceDetector = cv.FaceDetectorYN.create('/path/to/model', '', img.shape[:2])
6
7faces = faceDetector.detect(image)
8# 如果没有检测出人脸,则faces为NoneType而非一个空的numpy数组。这是由于OpenCV的Python bindings导致的。
9# 如果检测出人脸,则faces为一个len=2的Tuple,其中faces[1]为nx15的二维numpy数组(排列方式同上)。

OpenCV基于深度学习的人脸识别FaceRecognizerSF

人脸识别是利用人的脸部特征信息进行身份鉴别的技术。广义的人脸识别包括人脸图像采集与检测、人脸图像预处理、人脸特征提取、特征比对与分类等一系列技术。

人脸预处理

将检测到的人脸输入人脸识别模型前,通常需要先进行人脸对齐。人脸对齐利用检测部分提取到的关键点,与给定关键点之间计算变换矩阵,使用仿射变换对人脸进行变换,以减轻人脸尺度、姿态等对人脸特征提取的性能的影响。

C++下人脸对齐部分API(FaceRecognizerSF类)的使用方式:

// 初始化FaceRecognizerSFPtr<FaceRecognizerSF> faceRecognizer = FaceRecognizerSF::create(recog_model_path, '');

// 在人脸检测部分的基础上, 对齐检测到的首个人脸(faces.row(0)), 保存至aligned_face。Mat aligned_face;faceRecognizer->alignCrop(image, faces.row(0), aligned_face);

Python下人脸对齐部分API的使用方式:

# 初始化FaceRecognizerSF
recognizer = cv.FaceRecognizerSF.create(recog_model_path, '' )

# 在人脸检测部分的基础上, 对齐检测到的首个人脸(faces[1][0]), 保存至aligned_face。
aligned_face = recognizer.alignCrop(img, faces[1][0])

人脸特征提取

狭义的人脸识别模型仅作用于人脸特征提取过程。近年来,深度学习促进了人脸识别的发展,深度人脸识别模型也因其优越的性能得到了广泛应用[5]。深度人脸识别模型的训练离不开大规模训练集、高效的神经网络结构和训练损失函数。深度人脸识别模型在经过良好训练后,可以将预处理过的人脸图像转换为深度人脸特征用于后续的特征匹配。

OpenCV DNN Face所集成的深度人脸识别模型是由超球面损失函数监督、在百万名人数据集上训练的MobileNet轻量模型。将百万名人数据集[6],在使用基于元学习的自适应标签噪声清洗算法[7]进行数据清洗后,用于训练人脸识别模型,提高了人脸识别模型的性能。

模型结构使用了MobileNet[8],其利用深度可分离卷积减小了模型体积与计算量,是一种适用于移动设备的轻量级深度卷积神经网络。训练损失函数使用了SFace[9], SFace在超球面上施加由S型曲线控制的类内和类间约束以有裕度地减小类内距离而增大类间距离,从而训练出对训练噪声鲁棒的深度人脸模型,提高了人脸识别模型的性能。

人脸识别模型以尺寸为3*112*112的人脸图像对齐作为输入,输出维度为128维的人脸特征。

C++下特征提取部分API(FaceRecognizerSF类)的使用方式:

// 在上文的基础上, 获取对齐人脸的特征feature。Mat feature;faceRecognizer->feature(aligned_face, feature);

Python下特征提取部分API的使用方式:

# 在上文的基础上, 获取对齐人脸的特征feature。
feature = recognizer.feature(aligned_face)

人脸特征比对

对于不同人脸图像的人脸特征,经过人脸特征比对求出特征之间的距离,以确定不同人脸图像是否属于同一身份。当使用consine距离时,值越大,则人脸越相似身份越接近;当使用normL2距离时,值越小,则人脸越相似身份越接近。

C++下特征比对部分API(FaceRecognizerSF类)的使用方式:

// 在上文的基础上, 比对两张人脸的特征feature1,feature2以确认身份。// 使用consine距离作为指标double cos_score = faceRecognizer->match(feature1, feature2, FaceRecognizerSF::DisType::FR_COSINE);if(cos_score >= cosine_similar_thresh) {     // the same identity } else {    // different identities} 

// 使用normL2距离作为指标double L2_score = faceRecognizer->match(feature1, feature2, FaceRecognizerSF::DisType::FR_NORM_L2);if(L2_score <= l2norm_similar_thresh) {    // the same identity } else {    // different identities} 

Python下特征比对部分API的使用方式:

# 在上文的基础上, 比对两张人脸的特征feature1,feature2以确认身份。
# 使用consine距离作为指标
cosine_similarity_threshold = 0.363
cosine_score = recognizer.match(feature1, feature2, 0) 
if cosine_score >= cosine_similarity_threshold: 
    # 'the same identity'
else:
    # 'different identities'

# 使用normL2距离作为指标
l2_similarity_threshold = 1.128
l2_score = recognizer.match(feature1, feature2, 1)
if l2_score <= l2_similarity_threshold: 
    # 'the same identity'
else:
    # 'different identities' 

参考文献

[1] Liu, Wei, Dragomir, Anguelov, Dumitru, Erhan, Christian, Szegedy, Scott, Reed, Cheng-Yang, Fu, and Alexander C, Berg. 'Ssd: Single shot multibox detector.' . In ECCV, 2016.

[2] Howard, Andrew G, Menglong, Zhu, Bo, Chen, Dmitry, Kalenichenko, Weijun, Wang, Tobias, Weyand, Marco, Andreetto, and Hartwig, Adam. 'Mobilenets: Efficient convolutional neural networks for mobile vision applications'. In arXiv:1704.04861, 2017.

[3] Yang, Shuo, Ping, Luo, Chen Change, Loy, and Xiaoou, Tang. 'WIDER FACE: A Face Detection Benchmark.' . In CVPR, 2016.

[4] Peng, Hanyang, and Shiqi, Yu. 'A Systematic IoU-Related Method: Beyond Simplified Regression for Better Localization'. In TIP, 2021.

[5] Mei Wang and Weihong Deng. Deep face recognition: A survey. In Neurocomputing, 2021.

[6] Yandong Guo, Lei Zhang, Yuxiao Hu, Xiaodong He, and Jianfeng Gao. Ms-celeb-1m: A dataset and benchmark for large-scale face recognition. In ECCV, 2016.

[7] Yaobin Zhang, Weihong Deng, Yaoyao Zhong, Jiani Hu, Xian Li, Dongyue Zhao, and Dongchao Wen. Adaptive Label Noise Cleaning with Meta-Supervision for Deep Face Recognition. In ICCV, 2021.

[8] Andrew G. Howard, Menglong Zhu, Bo Chen, Dmitry Kalenichenko, Weijun Wang, Tobias Weyand, Marco Andreetto and Hartwig Adam. MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications. In arXiv:1704.04861, 2017.

[9] Yaoyao Zhong, Weihong Deng, Jiani Hu, Dongyue Zhao, Xian Li, and Dongchao Wen. SFace: sigmoid-constrained hypersphere loss for robust face recognition. In TIP, 2021.


(0)

相关推荐

  • 基于OpenCV的实时面部识别

    重磅干货,第一时间送达 我们将使用一些简单的代码来实现实时面部识别代码,我们可以对个人的面部进行预测. 现在,面部识别已成为生活中的一部分.因此,在介绍主题之前我们先看看实时面部识别示例.我们在手机. ...

  • 使用opencv进行实时人脸 眼睛 微笑检测

    代码: import cv2# 导入级联分类器引擎face_cascade = cv2.CascadeClassifier("opencv-master\data\haarcascades\ ...

  • 使用Python OpenCV预测年龄与性别

    本文转自:深度学习与计算机视觉 现在越来越多的应用程序与年龄和性别的自动分类相关,特别是自从社交平台和社交媒体兴起以后.尽管如此,现有的方法在真实图像上的性能仍然明显不足,特别是与最近人脸识别相关的任 ...

  • 使用OpenCV Python进行人脸识别

    先决条件 对图像分类的基本理解 Python 和深度学习知识 对深度学习中各种模块的概念理解 介绍 在这篇文章中,我们将看看什么是人脸识别?以及它与人脸检测有何不同? 我们先简单了解一下人脸识别的原理 ...

  • CV之Face Detection:Face Detection人脸检测原理及其常见分类技术

    CV之Face Detection:Face Detection人脸检测原理及其常见分类技术 人脸探测的原理 将图片转为HOG图片以后,结合其他辅助技术,如线性分类器,影像金字塔,滑动窗格检查机制,就 ...

  • 快速指南:使用OpenCV预处理神经网络中的面部图像的

    重磅干货,第一时间送达 本期将介绍脸部检测.眼睛检测:图像拉直.裁剪.调整大小.归一化等内容 目前,涉及面部分类的计算机视觉问题,通常都需要使用深度学习.因此在将图像输入神经网络之前,需要经过一个预处 ...

  • OpenCV入门教程(含人脸检测与常用图像处理示例等)

    在这篇文章中,我们将提供一些使用OpenCV的示例. 在OpenCV中混合图像 我们将提供一个逐步的示例,说明如何使用Python OpenCV混合图像.下面我们展示了目标图像和滤镜图像. 目标图像 ...

  • 平安夜,Python送你一顶圣诞帽 @微信官方

    最后知道真相的我眼泪掉下来 (还蒙在鼓里的同学请在微信最上方的搜索栏自行搜索『圣诞帽』) 好吧,你不给,咱自己来,不就是个帽子嘛. Python 在手,圣诞帽我有! OpenCV 库加上几张圣诞帽图片 ...

  • 上班摸鱼程序,再也不怕领导偷偷出现在身后了

    来源:Python 技术「ID: pythonall」 当你在上班摸鱼的时候,领导总会偷偷摸摸的出现在你的背后,例如小编曾经偷偷摸摸看<轻音>被抓包了.今天我们就用 Python 来破解这 ...

  • OpenCV深度学习人脸识别示例——看大佬如何秀恩爱

    PyImageSearch博主Adrian Rosebrock昨日发表博文,展示如何使用OpenCV的深度学习工具在小库上进行人脸识别.昨天是我们中国人的传统佳节--中秋节, Adrian推送博文时也 ...