TensorFlow MTCNN facenet 实现人脸识别

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视频学习资料:

=======================================================================

源码下载链接:https://download.csdn.net/download/yunge812/11373693

发布了70 篇原创文章 · 获赞 73 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/yunge812/article/details/86211824