一、MTCNN原理
MTCNN提出了一种Multi-task的人脸检测框架,将人脸检测和人脸特征点检测同时进行。论文使用3个CNN级联的方式。
算法流程
当给定一张照片的时候,将其缩放到不同尺度形成图像金字塔,以达到尺度不变。
Stage 1:使用P-Net是一个全卷积网络,用来生成候选窗和边框回归向量(bounding box regression vectors)。使用Bounding box regression的方法来校正这些候选窗,使用非极大值抑制(NMS)合并重叠的候选框。全卷积网络和Faster R-CNN中的RPN一脉相承。
Stage 2:使用N-Net改善候选窗。将通过P-Net的候选窗输入R-Net中,拒绝掉大部分false的窗口,继续使用Bounding box regression和NMS合并。
Stage 3:最后使用O-Net输出最终的人脸框和特征点位置。和第二步类似,但是不同的是生成5个特征点位置。
CNN结构
本文使用三个CNN,结构如图:
MTCNN由三个神经网络组成,P-NET R-NET O-NET 在使用这些网络之前,首先将图片所放到不同的尺度,形成一个图像金字塔。对于第一个P-NET网络输入为12*12*3的RGB图像,该网络要判断这个12*12的图像中(1)是否有人脸,(2)人脸框位置,(3)关键点位置。
同理,R-NET是在24*24*3的范围内寻找,O-NET是在48*48*3的范围内寻找。
每一层的输出都有三部分(1)是否有人脸,(2)人脸框位置,(3)关键点位置 三者对应三个损失。人脸判别部分,使用交叉熵损失;人脸框以及关键点判定,使用L2损失。最后三部分乘以自身的权重相加。
训练
这个算法需要实现三个任务的学习:人脸非人脸的分类,bounding box regression和人脸特征点定位。
(1)人脸检测
这就是一个分类任务,使用交叉熵损失函数即可:
(2)Bounding box regression
这是一个回归问题,使用平方和损失函数:
(3)人脸特征点定位
这也是一个回归问题,目标是5个特征点与标定好的数据的平方和损失:
二、使用方法
detect_face.py是MTCNN开源的代码,我们这里直接使用即可,det1.npy det2.npy det3.npy中储存着训练好的人脸参数,我们主要是想利用这些现有的开源程序来完成我们的功能。
2.1 创建MTCNN结构
pnet, rnet, onet = detect_face.create_mtcnn(sess, None)
2.2 读入图片,识别人脸
image_path = 'b.jpg'
img = misc.imread(image_path)
bounding_boxes, _ = detect_face.detect_face(img, minsize, pnet, rnet, onet, threshold, factor)
nrof_faces = bounding_boxes.shape[0]#人脸数目
2.3 画框
for face_position in bounding_boxes:
face_position=face_position.astype(int)
#print(face_position[0:4])
cv2.rectangle(img, (face_position[0]-10, face_position[1]-10), (face_position[2]+10, face_position[3]+10), (0, 255, 0),5)
使用MTCNN的完整代码如下
from scipy import misc
import tensorflow as tf
import detect_face
import cv2
import matplotlib.pyplot as plt
#%pylab inline
minsize = 20 # minimum size of face
threshold = [ 0.6, 0.7, 0.7 ] # three steps's threshold
factor = 0.709 # scale factor
gpu_memory_fraction=1.0
with tf.Graph().as_default():
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=gpu_memory_fraction)
sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False))
with sess.as_default():
pnet, rnet, onet = detect_face.create_mtcnn(sess, None)
image_path = 'b.jpg'
img = misc.imread(image_path)
bounding_boxes, _ = detect_face.detect_face(img, minsize, pnet, rnet, onet, threshold, factor)
nrof_faces = bounding_boxes.shape[0]#人脸数目
print('找到人脸数目为:{}'.format(nrof_faces))
for face_position in bounding_boxes:
face_position=face_position.astype(int)
#print(face_position[0:4])
cv2.rectangle(img, (face_position[0]-10, face_position[1]-10), (face_position[2]+10, face_position[3]+10), (0, 255, 0),5)
plt.imshow(img)
plt.show()
=======================================================================
最近新开的公众号,文章正在一篇篇的更新,
公众号名称:玩转电子世界
各位朋友有什么问题了可以直接在上面提问,我会一一进行解答的。
跟着阳光非宅男,一步步走进电子的世界。
关注之后回复 资料下载 关键词可以获得免费海量的视频学习资料下载~~!
已共享的学习视频资料,共享资料正在不断更新中。
共享机器学习/tensorflow视频学习资料:
=======================================================================