MTCNN用于检测出图片中的人脸,facenet用于识别人脸是谁。
一、整体思路
1 创建被识别目标的样本数据集。
这里我们选用刘翔和周杰伦来作为被识别的对象,因此,选取刘翔和周杰伦来作为基础的样本,提取出两者的数据集
1.1 利用MTCNN检测样本中的人脸,并且标识是l(刘翔) 还是 z(周杰伦)
1.2 利用facenet分别计算二者自己的embedding 并且保存。即样本的数据集
2 完成人脸识别
2.1 利用MTCNN检测样本中的人脸
2.2 利用facenet计算embedding
2.3 利用欧式距离计算他们分别和 l 和z embedding的距离 判断是 刘翔还是周杰伦还是其他人
二、创建样本数据集
2.1 前期准备
创建dataset/img文件夹 分别创建l 和 z的文件夹 存放样本图片
copy facenet.py 到当前文件夹
copy mtcnn的align文件夹到当前文件夹
copy 别人训练好的人脸识别模型models文件夹到当前文件夹
2.2 利用mtcnn识别其中的人脸,并且将识别出的结果存放在dataset/emb_face文件夹
def create_face(img_dir,out_face_dir):
# 获取 img 及其 label
img_list,name_list = file_processing.gen_files_labels(img_dir,postfix='jpg')
#创建MTCNN网络
face_detect = face_recognition.Facedetection() #初始化 Facedetection()
for img_path,name in zip(img_list,name_list):
# 读取图片
img = image_processing.read_image(img_path,resize_height=0,resize_width=0,normalization=False)
# 调用MTCNN来进行人脸检测
bounding_box,points = face_detect.detect_face(img)
bounding_box = bounding_box[:,0:4].astype(int)
bounding_box=bounding_box[0,:]
# 截取人脸图片
face_image = image_processing.crop_image(img,bounding_box)
# 截取人脸输出的路径
out_path = os.path.join(out_face_dir,name)
# 对人脸进行缩放 因为facenet要求人脸输入为160*160
face_image = image_processing.resize_image(face_image,resize_height,resize_width)
if not os.path.exists(out_path):
os.mkdir(out_path)
basename = os.path.basename(img_path) #获取文件名
out_path=os.path.join(out_path,basename) #保存人脸的绝对路径
image_processing.save_image(out_path,face_image)
2.3 计算样本的embedding
def create_embedding(model_path,emb_face_dir,out_emb_path,out_filename):
# 初始化facenetEmbedding
face_net = face_recognition.facenetEmbedding(model_path)
# 获取人脸img及其label
img_list,name_list = file_processing.gen_files_labels(emb_face_dir,postfix='jpg')
# 得到缩放的图片 并且归一化
img = image_processing.get_images(img_list,resize_height,resize_width,whiten=True)
compare_emb = face_net.get_embedding(img)
np.save(out_emb_path,compare_emb)
file_processing.write_data(out_filename,img_list,model='w')
其中,在上述计算时,需要用到 face_detect.detect_face(img) face_recognition.facenetEmbedding 两个函数,这两个函数分别就是检测人脸的函数以及计算embedding的函数,其定义如下
# -*-coding: utf-8 -*-
import facenet
import tensorflow as tf
import align.detect_face as detect_face
class facenetEmbedding:
def __init__(self, model_path):
self.sess = tf.InteractiveSession()
self.sess.run(tf.global_variables_initializer())
facenet.load_model(model_path)
self.images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0")
self.tf_embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0")
self.phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0")
def get_embedding(self, images):
feed_dict = {self.images_placeholder:images, self.phase_train_placeholder:False}
embedding = self.sess.run(self.tf_embeddings,feed_dict=feed_dict)
return embedding
def free(self):
self.sess.close()
class Facedetection:
def __init__(self):
self.minsize = 20
self.threshold = [0.6,0.7,0.7]
self.factor = 0.709
with tf.Graph().as_default():
sess = tf.Session()
with sess.as_default():
self.pnet,self.rnet,self.onet = detect_face.create_mtcnn(sess,None)
def detect_face(self,image):
bounding_boxes,points = detect_face.detect_face(image, self.minsize, self.pnet, self.rnet, self.onet, self.threshold, self.factor)
return bounding_boxes,points
def detection_face(img):
self.minsize = 20
self.threshold = [0.6,0.7,0.7]
self.factor = 0.709
with tf.Graph().as_default():
sess = tf.Session()
with sess.as_default():
pnet, rnet, onet = detect_face.create_mtcnn(sess, None)
bounding_boxes, points = detect_face.detect_face(img, minsize, pnet, rnet, onet, threshold, factor)
return bounding_boxes,points
通过定义两个class 来封装 mtcnn detect 以及 facenet embedding。
至于图像处理函数,包括保存,打开,缩放等函数,在这里就不过多解释了。
经过此步,在dataset/emb_face文件夹下 存放着刘翔和周杰伦的人脸,在dataset/emb/faceEmbedding.npy 存放着样本的embedding,在dataset/emb/name.txt中存放着两个人的名字标志。
三、人脸识别过程。
1 在dataset/test_images下存放待检测照片。
2 加载样本数据。
def load_dataset(dataset_path,filename):
compare_emb = np.load(dataset_path)
names_list = file_processing.read_data(filename)
return compare_emb,names_list
3 打开待检测图像,识别出人脸
file_path = os.path.join(image_path, file_names)
image = image_processing.read_image(file_path)
bounding_box,points = face_detect.detect_face(image)
bounding_box = bounding_box[:,0:4].astype(int)
4 和样本的embedding 进行比较
face_images = image_processing.get_crop_images(image,bounding_box,resize_height,resize_width,whiten=True)
pred_emb = face_net.get_embedding(face_images)
pred_name = compare_embedding(pred_emb,dataset_emb,names_list)
其中compare_embedding代表计算两个之间的距离,返回检测出的人物的名字
def compare_embedding(pred_emb,dataset_emb,names_list):
pred_num = len(pred_emb)
dataset_num = len(dataset_emb)
pred_name = []
for i in range(pred_num):
dist_list = []
for j in range(dataset_num):
dist = np.sqrt(np.sum(np.square(np.subtract(pred_emb[i,:],dataset_emb[j,:]))))
dist_list.append(dist)
min_value = min(dist_list)
#print(min_value)
if (min_value>0.85):
pred_name.append('unkonwn')
else:
name = names_list[dist_list.index(min_value)]
name = name.split(os.sep)[-2]
pred_name.append(name)
#print(pred_name)
return pred_name
5 画框 做标记
bgr_image = cv2.cvtColor(image,cv2.COLOR_RGB2BGR)
people_num = bounding_box.shape[0]
print("people num = %d"%bounding_box.shape[0])
image_processing.cv_show_image_text("face_recognition", bgr_image,bounding_box, pred_name)
=======================================================================
最近新开的公众号,文章正在一篇篇的更新,
公众号名称:玩转电子世界
各位朋友有什么问题了可以直接在上面提问,我会一一进行解答的。
跟着阳光非宅男,一步步走进电子的世界。
关注之后回复 资料下载 关键词可以获得免费海量的视频学习资料下载~~!
已共享的学习视频资料,共享资料正在不断更新中。
共享机器学习/tensorflow视频学习资料:
=======================================================================