上一篇文章中搭建了facenet人脸识别环境,并且运行compare.py比较两张人脸的欧氏距离,本文介绍实时人脸识别的方法。首先收集需要识别的人脸,然后通过opencv读取摄像头数据,计算两张人脸的欧式距离。

收集人脸

通过手机或者摄像头拍摄人像照片,要求一张照片只有一张脸,最好正面照,然后通过mtcnn识别人脸并将人脸裁剪出来。数据集的格式参照lfw,即文件夹名为人名(label),文件夹包含该label的人脸

1
2
3
4
5
6
7
$ ls data/faces
Huang_Zhen/  Li_Long/  Zhang_Wenjie/
# mtcnn performs face alignment and stores face thumbnails 
$ python src/align/align_dataset_mtcnn.py --image_size 160 --margin 32 data/faces data/faces_160
# 将 data/faces_160 目录下保存的人脸拷贝到 data/input_faces目录
$ ls data/input_faces/
Huang_Zhen.png  Li_Long.png  Zhang_Wenjie.png

读取摄像头

使用python-opencv读取摄像头frame

1
2
3
4
5
6
7
8
# open local camera
capture = cv2.VideoCapture(0)

while True:
    ret, frame = capture.read()
    if not ret:
    	break
    rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

计算人脸向量

输入人脸的路径,返回该人脸的向量embedding

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def generate_image_embedding(self, images):
    # Get input and output tensors
    images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0")
    embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0")
    phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0")

    stack_images = np.stack(images)
    feed_dict = {images_placeholder: stack_images,
                 phase_train_placeholder: False}
    return self.sess.run(embeddings, feed_dict=feed_dict)

计算欧式距离

1
2
3
4
5
6
7
8
def compare(self, face, compare_emb, face_labels):
    dist_list = []
    for i in range(len(compare_emb)):
        dist = np.sqrt(np.sum(np.square(np.subtract(face.embedding, compare_emb[i, :]))))
        dist_list.append(dist)
    min_dist = min(dist_list)
    index = dist_list.index(min_dist)
    return face_labels[index]