人脸检测和人脸对齐是人脸识别的前提,也是进行一切人人脸相关的人脸项目的开始步骤,本文将从常用的人脸检测的数据集,以及现在公用的比较好的方法开始讲述。
人脸检测的测试数据库有很多,这里仅选择FDDB和WIDER FACE,这个两个数据库都有官方长期维护,各种算法都会提交结果进行比较,而且很多早期数据库目前都已经饱和,没有比较意义。
第一个是2010年非约束环境人脸检测数据库FDDB:
FDDB总共2845张图像,5171张,人脸非约束环境,人脸的难度较大,有面部表情,双下巴,光照变化,穿戴,夸张发型,遮挡等难点,是目标最常用的数据库。有以下特点:
图像分辨率较小,所有图像的较长边缩放到450,也就是说所有图像都小于450450,最小标注人脸2020,包括彩色和灰度两类图像;
每张图像的人脸数量偏少,平均1.8人脸/图,绝大多数图像都只有一人脸;数据集完全公开
有其他隔离数据集无限制训练再FDDB测试,和FDDB十折交叉验证两种,鉴于FDDB图像数量较少,近几年论文提交结果也都是无限制训练再FDDB测试方式,所以,如果要和published methods提交结果比较,请照做。山世光老师也说十折交叉验证通常会高1~3%。
结果有离散分数discROC和连续分数contROC两种,discROC仅关心IoU是不是大于0.5,contROC是IoU越大越好。鉴于大家都采用无限制训练加FDDB测试的方式,detector会继承训练数据集的标注风格,继而影响contROC,所以discROC比较重要,contROC看看就行了,不用太在意。
FDDB在非深度学习的年代是极具挑战性的,很少能做到2000误检0.9以上,经典VJ detector在2000误检也只有0.6593,但在深度学习的年代,这个数据库目前也快接近饱和了,FDDB可以看做是资格赛,选手的正式水平请看下面的WIDER FACE。
第二个是目前2016年提出的,目前难度最大的WIDER FACE WIDER FACE: A Face Detection Benchmark:
Yang S, Luo P, Loy C C, et al. Wider face: A face detection benchmark [C]// CVPR, 2016: 5525-5533.
WIDER FACE总共32203图像,393703标注人脸,目前难度最大,各种难点比较全面:尺度,姿态,遮挡,表情,化妆,光照等。有以下特点有:
图像分辨率普遍偏高,所有图像的宽都缩放到1024,最小标注人脸10*10,都是彩色图像;
每张图像的人脸数据偏多,平均12.2人脸/图,密集小人脸非常多;
分训练集train/验证集val/测试集test,分别占40%/10%/50%,而且测试集的标注结果(ground truth)没有公开,需要提交结果给官方比较,更加公平公正,而且测试集非常大,结果可靠性极高;
根据EdgeBox的检测率情况划分为三个难度等级:Easy, Medium, Hard。
WIDER FACE是目前最常用的训练集,也是目前最大的公开训练集,人工标注的风格比较友好,适合训练。总之,WIDER FACE最难,结果最可靠(顶会论文也有不跑WIDER FACE的,即使论文中用WIDER FACE训练),论文给出经典方法VJ, DPM, ACF和Faceness在这个库上的性能水平,可以看出难度确实很大。
参考链接:https://blog.csdn.net/App_12062011/article/details/80537518
人脸识别中经常用到dlib以及opencv封装的人脸检测函数主要介绍两个:HOG特征的人脸检测,具体介绍参考连接,一个是CNN人人脸检测,使用的方法是基于 Maximum-Margin Object Detector ( MMOD ),该模型训练的过程比较简单,不需要大量的训练集,[更多的训练内容可以参考连接]( Maximum-Margin Object Detector ( MMOD )),模型参数下载连接.更多的opencv以及dlib人脸检测的方法以及性能对比参考网页,更多的dlib的操作和示例代码参考连接
detector= dlib.get_frontal_face_detector() # HOG特征检测人脸
faceRects = detector(frameDlibHogSmall, 1) # 参数1表示我们对图像进行向上采样1倍,这将使一切变的更大,进而让我们检测出更多的人脸
for faceRect in faceRects: #输出检测框
x1 = faceRect.left()
y1 = faceRect.top()
x2 = faceRectdetector.right()
y2 = faceRect.bottom()
dnnFaceDetector = dlib.cnn_face_detection_model_v1("./mmod_human_face_detector.dat")
faceRects = dnnFaceDetector(frameDlibHogSmall, 0)
for faceRect in faceRects:
x1 = faceRect.rect.left()
y1 = faceRect.rect.top()
x2 = faceRect.rect.right()
y2 = faceRect.rect.bottom()
进一步得到人脸检测框后可以根据已经训练好的人脸68个点的特诊检测器来对检测到的人脸的轮廓特征提取。具体使用的函数为dlib.shape_predictor(‘shape_predictor_68_face_landmarks.dat’),模型下载链接
具体实现代码:
import numpy as np
import cv2
import dlib
detector = dlib.get_frontal_face_detector() # 使用HOG特征得到人脸框,同样可以使用dlib中的cnn
predictor = dlib.shape_predictor('/home/zhoujie/model/dlib_model/shape_predictor_68_face_landmarks.dat')
# cv2读取图像
img = cv2.imread("picture.jpg")
# 取灰度
img_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
# 人脸数rects
rects = detector(img_gray, 0)
for i in range(len(rects)):
landmarks = np.matrix([[p.x, p.y] for p in predictor(img, rects[i]).parts()]) # 使用predictor来获取人脸中的轮廓部分
for idx, point in enumerate(landmarks):
# 68点的坐标
pos = (point[0, 0], point[0, 1])
print(idx+1, pos)
# 利用cv2.circle给每个特征点画一个圈,共68个
cv2.circle(img, pos, 2, color=(0, 255, 0))
# 利用cv2.putText输出1-68
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, str(idx+1), pos, font, 0.8, (0, 0, 255), 1,cv2.LINE_AA)
cv2.namedWindow("img", 2)
cv2.imshow("img", img)
cv2.waitKey(0)
得到人脸轮廓中的数据后根据之前加载的68个点的模板进行对齐,具体的实现代码如下。PS:当检测到的人脸为侧脸的时候提取到的关键点不足以进行仿射变换的时候,将不对其进行处理。所有一般要保证编号为10-37,43-47的关键点,也就是鼻子、左眼、右眼及上嘴唇部分的基准关键点存在,然后根据这些基准关键点集合计算相似变换矩阵。具体实现代码如下:
import cv2
import dlib
import sys
import numpy as np
import os
predicter_path = '/model/shape_predictor_68_face_landmarks.dat'
face_file_path = '/faces/inesta.jpg'# 要使用的图片,图片放在当前文件夹中
# 导入人脸检测模型
detector = dlib.get_frontal_face_detector()
# 导入检测人脸特征点的模型
sp = dlib.shape_predictor(predicter_path)
# 读入图片
bgr_img = cv2.imread(face_file_path)
if bgr_img is None:
print("Sorry, we could not load '{}' as an image".format(face_file_path))
exit()
# opencv的颜色空间是BGR,需要转为RGB才能用在dlib中
rgb_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2RGB)
# 检测图片中的人脸
dets = detector(rgb_img, 1)
# 检测到的人脸数量
num_faces = len(dets)
if num_faces == 0:
print("Sorry, there were no faces found in '{}'".format(face_file_path))
exit()
# 识别人脸特征点,并保存下来
faces = dlib.full_object_detections()
for det in dets:
faces.append(sp(rgb_img, det))
# 人脸对齐,当关键点较少时不做对齐处理
images = dlib.get_face_chips(rgb_img, faces, size=320)
# 显示计数,按照这个计数创建窗口
image_cnt = 0
# 显示对齐结果
for image in images:
image_cnt += 1
cv_rgb_image = np.array(image).astype(np.uint8)# 先转换为numpy数组
cv_bgr_image = cv2.cvtColor(cv_rgb_image, cv2.COLOR_RGB2BGR)# opencv下颜色空间为bgr,所以从rgb转换为bgr
cv2.imshow('%s'%(image_cnt), cv_bgr_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
更多的dlib人脸检测以及opencv中的人来鸟检测和对齐方法参考githuh
主要解决的是人脸检测以及人脸对齐的问题。提出了三个层级的网络 PNet、RNet、 ONet三个层级网络。由粗略检测到精细检测。逐步实现最终的人脸检测和人脸对其。在FDDB和WIDER FACE两个数据集中的人脸检测以及AFLW数据集中的人脸对齐任务任务达到 state-of-the-art。在实时应用中达到较好的即时性。
网络的主要框架如上图所示:首先针对图片中人脸的大小可能不一的情况按照将图片按照一定的比例不断的resize到不同的尺寸作为输入。
MTCNN主要包括三层网络,
根据上述网络结构检测出人脸后得出人脸对应的box以及5个人脸特征点,在给定5个点的temple的基础上进行仿射变换得到对齐的人脸。