精华内容
参与话题
问答
  • Facenet 原理介绍

    万次阅读 2018-06-22 17:01:25
    引子[编辑 | 编辑源代码] 这篇wiki主要介绍facenet人脸相似比较的基本原理,另外两篇wiki主要介绍基于tensorflow实现facenet的准确率测试及源码解读。  经过在网上的一番搜索,找到了facenet实现人脸聚类的论文和...

    引子[编辑 | 编辑源代码]

       这篇wiki主要介绍facenet人脸相似比较的基本原理,另外两篇wiki主要介绍基于tensorflow实现facenet的准确率测试及源码解读。
    

      经过在网上的一番搜索,找到了facenet实现人脸聚类的论文和论文解读,以及github上根据facenet论文并结合tensorflow实现的开源代码。相关链接如下:

       facenet github实现   https://github.com/davidsandberg/facenet
       facenet 论文  用A Unified Embedding for Face Recognition and Clustering这个名字在google中搜索既能找到
       facenet论文解读  http://blog.csdn.net/chenriwei2/article/details/45031677
    

    facenet 简介[编辑 | 编辑源代码]

    直接学习图像到欧式空间上点的映射,两张图像所对应的特征的欧式空间上的点的距离直接对应着两个图像是否相似。如下图:


    上图一个简单的示例,其中图中的数字表示这图像特征之间的欧式距离,可以看到,图像的类内距离明显的小于类间距离,阈值大约为1.1左右。针对facenet原理将会在另一篇wiki中介绍。

    facenet structure[编辑 | 编辑源代码]


    如上图所示
    batch :是指输入的人脸图像样本,这里的样本是已经经过人脸检测找到人脸并裁剪到固定尺寸(例如160x160)的图片样本。
    Deep architecture:指的是采用一种深入学习架构例如imagenet历年冠军网络中的ZF,googlenet等。
    L2 :是指特征归一化(使其特征的||f(x)||2=1,这里是2次方的意思。这样所有图像的特征都会被映射到一个超球面上)
    Embeddings: 就是前面经过深度学习网络,L2归一化后生成的特征向量(这个特征向量就代表了输入的一张样本图片)
    riplet Loss: 就是有三张图片输入的Loss(之前的都是Double Loss或者 是 SingleLoss)。直接学习特征间的可分性:相同身份之间的特征距离要尽可能的小,而不同身份之间的特征距离要尽可能的大。

    googlenet 网络介绍

    上一节提到的Deep architecture就是指深度网络,而论文中举例的就是googlelet网络。
    GoogLeNet, 是google公司在推出的,获得了2014年ILSVRC挑战赛冠军,将Top5 的错误率降低到6.67%. 一个22层的深度网络,论文在http://arxiv.org/pdf/1409.4842v1.pdf

    googlenet在基础的CNN卷积、池化、卷积、池化、全连接这样结构基础上做了一些变形处理。


    下面从前几层举例介绍下:
    其输入及卷积层的参数配置在论文中都有,这里主要是根据这些参数计算增加了些自己的理解。注意模型是从下到上看的
    a, 第一个卷积层
    原始数据,输入为224*224*3
    第一层卷积层 conv1 ,pad是3,64个特征,7*7 步长为2,输出特征为 112*112*64,然后进行relu,有padding的,所以输出的计算公式为:
    输出长度:Out = in/stride
    输出宽度:Out = in/stride

    b,线性整流函数(Rectified Linear Unit, ReLU),又称修正线性单元, 是一种人工神经网络中常用的激活函数(activation function),通常指代以斜坡函数及其变种为代表的非线性函数。


    c,第一个池化层 经过pool1(红色的max pool) 进行pooling 3*3的核,步长为2, [(112 - 3+1)/2]+1 = 56 特征为56*56*64 , 然后进行norm。认为这里的池化层输出尺寸计算与卷积层一样。
    其中LocalRespNormal的作用是归一化。其细节是对一个局部的输入区域进行的归一化(激活a被加一个归一化权重(分母部分)生成了新的激活b)。

    d, Inception子网络
    第三层开始时 inception module ,这个的思想受到使用不同尺度的Gabor过滤器来处理多尺度问题,inception module采用不同尺度的卷积核来处理问题。这里采用的是inception含降维模型。这个模型的作用如下:
    1 . 采用不同大小的卷积核意味着不同大小的感受野,最后拼接意味着不同尺度特征的融合; 
    2 . 之所以卷积核大小采用1、3和5,主要是为了方便对齐。设定卷积步长stride=1之后,只要分别设定pad=0、1、2,那么卷积之后便可以得到相同维度的特征,然后这些特征就可以直接拼接在一起了; 
    3 . 文章说很多地方都表明pooling挺有效,所以Inception里面也嵌入了。 
    4 . 网络越到后面,特征越抽象,而且每个特征所涉及的感受野也更大了,因此随着层数的增加,3x3和5x5卷积的比例也要增加。


    展开全文
  • 利用MTCNN和facenet实现人脸检测和人脸识别

    万次阅读 多人点赞 2018-12-09 14:29:07
    利用MTCNN和facenet实现人脸检测和人脸识别 人脸检测和人脸识别技术算是目前人工智能方面应用最成熟的技术了。本博客将利用mtcnn和faceNet搭建一个实现人脸检测和人脸识别的系统。基本思路也很简单,先利用mtcnn的...

    利用MTCNN和facenet实现人脸检测和人脸识别

        人脸检测和人脸识别技术算是目前人工智能方面应用最成熟的技术了。本博客将利用mtcnn和faceNet搭建一个实现人脸检测和人脸识别的系统。基本思路也很简单,先利用mtcnn的进行人脸检测,当然也可以使用其他的人脸检测方法,如Dilb,OpenCV,OpenFace人脸检测等等,然后再利用faceNet进行人脸识别,faceNet可简单看成是提取人脸特征的CNN网络,这个特征就是embadding了,有了人脸特征embadding,最后一步,就只需要与数据库人脸特征进行相似性比较,即可完成人脸识别的任务。

       老规矩,先上Github源码:记得给个“Star”哦,不然,对不起我的苦劳!!!

       本博客Github源码: https://github.com/PanJinquan/Face_Detection_Recognition/tree/master/faceRecognition

    FaceNet的人脸识别效果并不算好,相比InsightFace模型,就差很多。目前使用InsightFace模型测试,在开数据集可以达到99.6%,在自建的数据集可以达到93%的准确率,比虹软的人脸识别率还高一点,关于InsightFace模型的项目,我还在整理,网友慢慢期待哈,不急!


    目录

    利用MTCNN和facenet实现人脸检测和人脸识别

    一、项目结构:

    二、实现流程

    三、Multi-task CNN(MTCNN)人脸检测

    四、faceNet人脸识别

    五、产生数据库

    (1)制作人脸数据图库:

    (2)生成embedding数据库

    六、人脸识别过程

    (1)加载人脸数据库

    (2)进行人脸检测

    (3)人脸识别(比较相似性)

    (4)人脸识别效果

    七、模型测评

    八、参考资料:


     

    一、项目结构:

        打开FaceNet Github地址: https://github.com/davidsandberg/facenet,把我们需要的文件拷贝到自己独立的工程中,(1)align文件夹,(2)facenet.py文件:

    align:这个文件夹是从facenet中拷贝的,https://github.com/davidsandberg/facenet/tree/master/src/align,主要是MTCNN人脸检测的相关文件

    facenet.py:这个Python文件也是从facenet中拷贝的,https://github.com/davidsandberg/facenet/blob/master/src/facenet.py

        其他文件介绍

    dataset:这个文件夹主要存放数据,如人脸数据库

    utils:这个文件是工具类文件,用于文件读写,图像相关操作的函数方法等

    models:存放facenet预训练模型,百度网盘下载地址链接: https://pan.baidu.com/s/1hAK9ylURkbeH52BtSSGWsw 提取码: jf1n 

    Pre-trained models:

    Model name LFW accuracy Training dataset Architecture
    20180408-102900 0.9905 CASIA-WebFace Inception ResNet v1
    20180402-114759 0.9965 VGGFace2 Inception ResNet v1

    NOTE: If you use any of the models, please do not forget to give proper credit to those providing the training dataset as well.

    二、实现流程

    1.通过MTCNN人脸检测模型,从照片中提取人脸图像。

    2.把人脸图像输入到FaceNet,计算Embedding的特征向量。

    3.比较特征向量间的欧式距离,判断是否为同一人,例如当特征距离小于1的时候认为是同一个人,特征距离大于1的时候认为是不同人。


    三、Multi-task CNN(MTCNN)人脸检测

        人脸检测方法很多,如Dilb,OpenCV,OpenFace人脸检测等等,这里使用MTCNN进行人脸检测,一方面是因为其检测精度确实不错,另一方面facenet工程中,已经提供了用于人脸检测的mtcnn接口。  MTCNN是多任务级联CNN的人脸检测深度学习模型,该模型中综合考虑了人脸边框回归和面部关键点检测。在facenet工程中的位置是align/detect_face.py ,它的参数模型也保存在align文件夹下,分别是det1.npy,det2.npy,det3.npy

    参考资料:

    https://blog.csdn.net/qq_28618765/article/details/78127967

    https://blog.csdn.net/gubenpeiyuan/article/details/80475307

        MTCNN一个深度卷积多任务的框架,这个框架利用了检测和对准之间固有的关系来增强他们的性能。特别是,在预测人脸及脸部标记点的时候,通过3个CNN级联的方式对任务进行从粗到精的处理。

    Stage 1:使用P-Net是一个全卷积网络,用来生成候选窗和边框回归向量(bounding box regression vectors)。使用Bounding box regression的方法来校正这些候选窗,使用非极大值抑制(NMS)合并重叠的候选框。全卷积网络和Faster R-CNN中的RPN一脉相承。

    Stage 2:使用R-Net改善候选窗。将通过P-Net的候选窗输入R-Net中,拒绝掉大部分false的窗口,继续使用Bounding box regression和NMS合并。

    Stage 3:最后使用O-Net输出最终的人脸框和特征点位置。和第二步类似,但是不同的是生成5个特征点位置。

        这里提供一个使用MTCNN进行人脸检测的方法:

    def detection_face(img):
        minsize = 20  # minimum size of face
        threshold = [0.6, 0.7, 0.7]  # three steps's threshold
        factor = 0.709  # scale factor
        print('Creating networks and loading parameters')
        with tf.Graph().as_default():
            # gpu_memory_fraction = 1.0
            # 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))
            sess = tf.Session()
            with sess.as_default():
                pnet, rnet, onet = detect_face.create_mtcnn(sess, None)
                bboxes, landmarks = detect_face.detect_face(img, minsize, pnet, rnet, onet, threshold, factor)
        landmarks = np.transpose(landmarks)
        bboxes = bboxes.astype(int)
        bboxes = [b[:4] for b in bboxes]
        landmarks_list=[]
        for landmark in landmarks:
            face_landmarks = [[landmark[j], landmark[j + 5]] for j in range(5)]
            landmarks_list.append(face_landmarks)
        return bboxes,landmarks_list

        当然,实际应用中,建议还是封装成一个类吧,方面初始化和单独调用:

    注意:mtcnn人脸检测获得bboxes并不一定是正方形的矩形框,参数fixed指定等宽或者等高的bboxes,其实现方法可以参考get_square_bboxes()方法。当然啦,你也可以不调用get_square_bboxes()方法,直接resize成指定大小,也是OK的。

    class Facedetection:
        def __init__(self):
            self.minsize = 30  # minimum size of face
            self.threshold = [0.6, 0.7, 0.7]  # three steps's threshold
            self.factor = 0.709  # scale factor
            print('Creating networks and loading parameters')
            with tf.Graph().as_default():
                # gpu_memory_fraction = 1.0
                # 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))
                sess = tf.Session()
                with sess.as_default():
                    self.pnet, self.rnet, self.onet = detect_face.create_mtcnn(sess, None)
        def detect_face(self,image,fixed=None):
            '''
            mtcnn人脸检测,
            PS:人脸检测获得bboxes并不一定是正方形的矩形框,参数fixed指定等宽或者等高的bboxes
            :param image:
            :param fixed:
            :return:
            '''
            bboxes, landmarks = detect_face.detect_face(image, self.minsize, self.pnet, self.rnet, self.onet, self.threshold, self.factor)
            landmarks_list = []
            landmarks=np.transpose(landmarks)
            bboxes=bboxes.astype(int)
            bboxes = [b[:4] for b in bboxes]
            for landmark in landmarks:
                face_landmarks = [[landmark[j], landmark[j + 5]] for j in range(5)]
                landmarks_list.append(face_landmarks)
            if fixed is not None:
                bboxes,landmarks_list=self.get_square_bboxes(bboxes, landmarks_list, fixed)
            return bboxes,landmarks_list
    
        def get_square_bboxes(self, bboxes, landmarks, fixed="height"):
            '''
            获得等宽或者等高的bboxes
            :param bboxes:
            :param landmarks:
            :param fixed: width or height
            :return:
            '''
            new_bboxes = []
            for bbox in bboxes:
                x1, y1, x2, y2 = bbox
                w = x2 - x1
                h = y2 - y1
                center_x, center_y = (int((x1 + x2) / 2), int((y1 + y2) / 2))
                if fixed == "height":
                    dd = h / 2
                elif fixed == 'width':
                    dd = w / 2
                x11 = int(center_x - dd)
                y11 = int(center_y - dd)
                x22 = int(center_x + dd)
                y22 = int(center_y + dd)
                new_bbox = (x11, y11, x22, y22)
                new_bboxes.append(new_bbox)
            return new_bboxes, landmarks

    四、faceNet人脸识别

        FaceNet Github地址: https://github.com/davidsandberg/facenet

        参考资料:https://blog.csdn.net/fire_light_/article/details/79592804

        Google工程师Florian Schroff,Dmitry Kalenichenko,James Philbin提出了人脸识别FaceNet模型,该模型没有用传统的softmax的方式去进行分类学习,而是抽取其中某一层作为特征,学习一个从图像到欧式空间的编码方法,然后基于这个编码再做人脸识别、人脸验证和人脸聚类等。

        FaceNet主要用于验证人脸是否为同一个人,通过人脸识别这个人是谁。FaceNet的主要思想是把人脸图像映射到一个多维空间,通过空间距离表示人脸的相似度。同个人脸图像的空间距离比较小,不同人脸图像的空间距离比较大。这样通过人脸图像的空间映射就可以实现人脸识别,FaceNet中采用基于深度神经网络的图像映射方法和基于triplets(三联子)的loss函数训练神经网络,网络直接输出为128维度的向量空间。

        FaceNet的网络结构如下图所示,其中Batch表示人脸的训练数据,接下来是深度卷积神经网络,然后采用L2归一化操作,得到人脸图像的特征表示,最后为三元组(Triplet Loss)的损失函数。

        下面是鄙人已经封装好的facenetEmbedding类,其中类函数get_embedding(self,images)方法用于提取facenet的人脸特征embadding,有了人脸embadding特征,就可以比较人脸相似性啦!

    class facenetEmbedding:
        def __init__(self,model_path):
            self.sess = tf.InteractiveSession()
            self.sess.run(tf.global_variables_initializer())
            # Load the model
            facenet.load_model(model_path)
            # Get input and output tensors
            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()

    五、产生数据库

       既然是人脸识别,数据库肯定要有已知人脸的数据库,不然怎么知道被检测的人脸是哪位大神,所以先制作人脸数据库。

    (1)制作人脸数据图库:

        把相关大神的人像收集放在dataset/images文件夹下:

     

    特别说明:

    1. 这里只收集了4张胡歌和4张周杰伦的单人照片,
    2. 注意制作人脸数据图库时,所使用的照片必须是单人照片!!!
    3. 若需要新增图库,只需在dataset/images下,新建一个文件夹,如,新增“xietingfeng”(谢霆锋)的文件夹,然后把谢霆锋的单人照片放在里面即可,图片名称可以是任意
    4. 函数image_list,names_list=file_processing.gen_files_labels(images_dir,postfix='jpg')可以获取目录images_dir下所有文件,包括子目录下的所有文件路径(image_list),其中names_list就是子目录的文件名,一般子目录作为样本的标签。

    (2)生成embedding数据库

        有了人脸数据图库,就可以使用create_dataset.py生成embedding数据库(人脸特征),后面待检测识别的人脸,只需要与这些embedding数据库(人脸特征)进行相似性比较,就可以识别人脸啦!!!!

    opencv-python的imread()函数并不支持中文路径,这里在提供一个函数read_image_gbk()方便读取中文路径的图像。详细请看image_processing.py文件

    # -*-coding: utf-8 -*-
    """
        @Project: faceRecognition
        @File   : create_dataset.py
        @Author : panjq
        @E-mail : pan_jinquan@163.com
        @Date   : 2018-12-07 11:31:09
    """
    import numpy as np
    from utils import image_processing , file_processing,debug
    import face_recognition
    import cv2
    import os
    
    resize_width = 160
    resize_height = 160
    
    
    def get_face_embedding(model_path,files_list, names_list):
        '''
        获得embedding数据
        :param files_list: 图像列表
        :param names_list: 与files_list一一的名称列表
        :return:
        '''
        # 转换颜色空间RGB or BGR
        colorSpace="RGB"
        # 初始化mtcnn人脸检测
        face_detect = face_recognition.Facedetection()
        # 初始化facenet
        face_net = face_recognition.facenetEmbedding(model_path)
    
        embeddings=[] # 用于保存人脸特征数据库
        label_list=[] # 保存人脸label的名称,与embeddings一一对应
        for image_path, name in zip(files_list, names_list):
            print("processing image :{}".format(image_path))
            # image_path='E:/Face/dataset/bzl/subjectphoto_with_name/谢伟林_179_180.jpg'
            image = image_processing.read_image_gbk(image_path, colorSpace=colorSpace)
            # 进行人脸检测,获得bounding_box
            bboxes, landmarks = face_detect.detect_face(image)
            bboxes, landmarks =face_detect.get_square_bboxes(bboxes, landmarks,fixed="height")
            # image_processing.show_image_boxes("image",image,bboxes)
            if bboxes == [] or landmarks == []:
                print("-----no face")
                continue
            if len(bboxes) >= 2 or len(landmarks) >= 2:
                print("-----image have {} faces".format(len(bboxes)))
                continue
            # 获得人脸区域
            face_images = image_processing.get_bboxes_image(image, bboxes, resize_height, resize_width)
            # 人脸预处理,归一化
            face_images = image_processing.get_prewhiten_images(face_images,normalization=True)
            # 获得人脸特征
            pred_emb = face_net.get_embedding(face_images)
            embeddings.append(pred_emb)
            # 可以选择保存image_list或者names_list作为人脸的标签
            # 测试时建议保存image_list,这样方便知道被检测人脸与哪一张图片相似
            # label_list.append(image_path)
            label_list.append(name)
        return embeddings,label_list
    
    def create_face_embedding(model_path,dataset_path,out_emb_path,out_filename):
        '''
    
        :param model_path: faceNet模型路径
        :param dataset_path: 人脸数据库路径,每一类单独一个文件夹
        :param out_emb_path: 输出embeddings的路径
        :param out_filename: 输出与embeddings一一对应的标签
        :return: None
        '''
        files_list,names_list=file_processing.gen_files_labels(dataset_path,postfix='jpg')
        embeddings,label_list=get_face_embedding(model_path,files_list, names_list)
        print("label_list:{}".format(label_list))
        print("have {} label".format(len(label_list)))
    
        embeddings=np.asarray(embeddings)
        np.save(out_emb_path, embeddings)
        file_processing.write_data(out_filename, label_list, model='w')
    
    if __name__ == '__main__':
        model_path = 'models/20180408-102900'
        dataset_path='dataset/images'
        out_emb_path = 'dataset/emb/faceEmbedding.npy'
        out_filename = 'dataset/emb/name.txt'

    六、人脸识别过程

    (1)加载人脸数据库

         把上面制作的,已知的人脸数据库加载进来:

    def load_dataset(dataset_path,filename):
        '''
        加载人脸数据库
        :param dataset_path: embedding.npy文件(faceEmbedding.npy)
        :param filename: labels文件路径路径(name.txt)
        :return:
        '''
        compare_emb=np.load(dataset_path)
        names_list=file_processing.read_data(filename,split=False)
        return compare_emb,names_list

    (2)进行人脸检测

    def face_recognition_image(model_path,dataset_path, filename,image_path):
        # 加载数据库的数据
        dataset_emb,names_list=load_dataset(dataset_path, filename)
        # 初始化mtcnn人脸检测
        face_detect=face_recognition.Facedetection()
        # 初始化facenet
        face_net=face_recognition.facenetEmbedding(model_path)
    
        image = image_processing.read_image_gbk(image_path)
        # 获取 判断标识 bounding_box crop_image
        bboxes, landmarks = face_detect.detect_face(image)
        bboxes, landmarks = face_detect.get_square_bboxes(bboxes, landmarks, fixed="height")
        if bboxes == [] or landmarks == []:
            print("-----no face")
            exit(0)
        print("-----image have {} faces".format(len(bboxes)))
        face_images = image_processing.get_bboxes_image(image, bboxes, resize_height, resize_width)
        face_images = image_processing.get_prewhiten_images(face_images)
        pred_emb=face_net.get_embedding(face_images)
        pred_name,pred_score=compare_embadding(pred_emb, dataset_emb, names_list)
        # 在图像上绘制人脸边框和识别的结果
        show_info=[ n+':'+str(s)[:5] for n,s in zip(pred_name,pred_score)]
        image_processing.show_image_text("face_recognition", image,bboxes,show_info)

    (3)人脸识别(比较相似性)

        比较特征向量间的欧式距离

    
    def compare_embadding(pred_emb, dataset_emb, names_list,threshold=0.65):
        # 为bounding_box 匹配标签
        pred_num = len(pred_emb)
        dataset_num = len(dataset_emb)
        pred_name = []
        pred_score=[]
        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)
            pred_score.append(min_value)
            if (min_value > threshold):
                pred_name.append('unknow')
            else:
                pred_name.append(names_list[dist_list.index(min_value)])
        return pred_name,pred_score
    

    (4)人脸识别效果

        一切准备好了,开始run:

    if __name__=='__main__':
        model_path='models/20180408-102900'
        dataset_path='dataset/emb/faceEmbedding.npy'
        filename='dataset/emb/name.txt'
        image_path='dataset/test_images/1.jpg'
        face_recognition_image(model_path, dataset_path, filename,image_path)

        说明:

    为了方便测试,  这里以文件的路径作为人脸label,这样方便知道被检测人脸与哪一张图片最相似

    ./dataset/emb_face\huge\huge_1.jpg
    ./dataset/emb_face\huge\huge_2.jpg
    ./dataset/emb_face\huge\huge_3.jpg
    ./dataset/emb_face\huge\huge_4.jpg
    ./dataset/emb_face\zhoujielun\zhoujielun_1.jpg
    ./dataset/emb_face\zhoujielun\zhoujielun_2.jpg
    ./dataset/emb_face\zhoujielun\zhoujielun_3.jpg
    ./dataset/emb_face\zhoujielun\zhoujielun_4.jpg

    对应的label是:

    huge
    huge
    huge
    huge
    zhoujielun
    zhoujielun
    zhoujielun
    zhoujielun

    七、模型测评

        为了对faceNed性能进行测评,这里提供一个测评文件:evaluation_test.py,该文件会绘制测试文件的ROC曲线,并给出最优阈值,以及FPR, TPR, AUC等参数。

    这里的测试数据集是agedb_30,该数据集共有12000张,分为6000对照片,每对照片有一个label,即True和False,对应1和0,表示该对照片是否是同一个人;利用该数据集,就可以绘制模型的ROC曲线了

    # -*- coding: utf-8 -*-
    
    import os
    import pickle
    from utils import image_processing,file_processing,evaluation
    import cv2
    import PIL.Image as Image
    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn import metrics
    import face_recognition
    
    def load_npy(dir_path):
        issames_path=os.path.join(dir_path,"issames.npy")
        pred_score_path=os.path.join(dir_path,"pred_score.npy")
        issames=np.load(issames_path)
        pred_score=np.load(pred_score_path)
        return pred_score,issames
    
    def load_bin(path, image_size=[112,112]):
        '''
        加载人脸bin文件数据,bin_files = ['agedb_30', 'cfp_fp', 'lfw', 'calfw', 'cfp_ff', 'cplfw', 'vgg2_fp']
        :param path:
        :param image_size:
        :return:
        '''
        bins, issame_list = pickle.load(open(path, 'rb'), encoding='bytes')
        data=[]
        for i in range(len(bins)):
            _bin = bins[i]
            img = cv2.imdecode(_bin, -1) # opencv image is bgr
            img = image_processing.resize_image(img,resize_height=image_size[0],resize_width=image_size[1])
            # image_processing.show_image("src",img)
            data.append(img)
            i += 1
            if i % 1000 == 0:
                print('loading bin', i)
        data = np.array(data)
        issames = np.array(issame_list)
        return data, issames
    
    def split_data(data):
        '''
        按照奇偶项分割数据
        :param data:
        :return:
        '''
        data1 = data[0::2]
        data2 = data[1::2]
        return data1,data2
    
    def get_pair_scores(faces_data, issames_data, model_path, save_path=None):
        '''
        计算分数
        :param faces_data:
        :param issames_data:
        :param model_path: insightFace模型路径
        :param save_path:
        :return:
        '''
        faces_list1,faces_list2 = split_data(faces_data)
        face_net=face_recognition.facenetEmbedding(model_path)
    
        pred_score=[]
        i=0
        for face1,face2,issame in zip(faces_list1, faces_list2, issames_data):
            # pred_id, pred_scores = faceRec.predict(faces)
            # 或者使用get_faces_embedding()获得embedding,再比较compare_embedding()
            face_images1 = image_processing.get_prewhiten_images([face1],normalization=False)
            face_images2 = image_processing.get_prewhiten_images([face2],normalization=False)
    
            face_emb1=face_net.get_embedding(face_images1)
            face_emb2=face_net.get_embedding(face_images2)
    
            # face_emb1 = face_net.get_faces_embedding([face1])
            # face_emb2 = face_net.get_faces_embedding([face2])
            dist = np.sqrt(np.sum(np.square(np.subtract(face_emb1, face_emb2))))
            pred_score.append(dist)
            i += 1
            if i % 100 == 0:
                print('processing data :', i)
        pred_score=np.array(pred_score).reshape(-1)
        issames_data= issames_data + 0 # 将true和false转为1/0
        if save_path is not None:
            issames_path = os.path.join(save_path, "issames.npy")
            pred_score_path = os.path.join(save_path, "pred_score.npy")
            np.save(issames_path, issames_data)
            np.save(pred_score_path,pred_score)
        return pred_score, issames_data
    
    if __name__=='__main__':
        # bin_files = ['agedb_30', 'cfp_fp', 'lfw', 'calfw', 'cfp_ff', 'cplfw', 'vgg2_fp']
        bin_path='./dataset/faces_emore/agedb_30.bin'
        model_path = './models/20180408-102900'
        # 加载bin测试数据
        faces_data, issames_data=load_bin(bin_path,image_size=[160,160])
    
        # 计算分数
        save_path="./dataset/faces_emore"
        pred_score, issames_data=get_pair_scores(faces_data, issames_data, model_path, save_path=save_path)
        pred_score, issames_data=load_npy(dir_path=save_path)
    
        # 计算roc曲线
        fpr, tpr, roc_auc, threshold, optimal_idx=evaluation.get_roc_curve(y_true=issames_data, y_score=pred_score, invert=True, plot_roc=True)
    
        print("fpr:{}".format(fpr))
        print("tpr:{}".format(tpr))
        print("threshold:{}".format(threshold))
        print("roc_auc:{}".format(roc_auc))
        print("optimal_idx :{},best_threshold :{} ".format(optimal_idx,threshold[optimal_idx]))
    
        # 测评数据保存
        evaluation.save_evaluation(fpr, tpr, roc_auc, "evaluation.npz")
    
        # 加载测评数据
        fpr, tpr, roc_auc=evaluation.load_evaluation("evaluation.npz")
        evaluation.plot_roc_curve(fpr_list=[fpr], tpr_list=[tpr], roc_auc_list=[roc_auc], line_names=["FaceNet"])
    

    对应的ROC曲线如下:optimal_idx :1038,最佳阈值:best_threshold :1.1444087028503418 

    FaceNet的人脸识别效果并不算好,相比InsightFace模型,就差很多。目前使用InsightFace模型测试,在开数据集可以达到99.6%,在自建的数据集可以达到93%的准确率,比虹软的人脸识别率还高一点,关于InsightFace模型的项目,我还在整理,网友慢慢期待哈,不急!


    八、参考资料:

    【1】《如何应用MTCNN和FaceNet模型实现人脸检测及识别》http://www.uml.org.cn/ai/201806124.asp

     

    如果你觉得该帖子帮到你,还望贵人多多支持,鄙人会再接再厉,继续努力的~

    展开全文
  • 文章地址:史上最全的FaceNet源码使用方法和讲解(一)(附预训练模型下载)转载请注明出处。 前提条件:已安装并配置好Tensorflow的运行环境。 第一步:准备facenet程序: 一、下载FaceNet源码。 下载地址:...

    文章地址:史上最全的FaceNet源码使用方法和讲解(一)(附预训练模型下载)转载请注明出处。


    前提条件:已安装并配置好Tensorflow的运行环境。

    第一步:准备facenet程序:

    一、下载FaceNet源码。

    下载地址:facenet源码

    二、精简代码。

    作者在代码里实现了很多功能,但是对于初学者来说,很多代码是没有必要的,反倒找不到学习这个程序的入口。建议先精简一下代码,便于读懂代码:新建一个文件夹,取名:facenet,把源码中的src文件夹直接拷贝过来。

    注:便于大家能够看懂代码,以上两步我已经完成,同时,自己运行程序之后,还对里边的代码做了详细的注释,如果想先了解facenet的源码,强烈建议下载这个,下载地址:facenet精简版

    当然,大家别忘了顺手点个星哦~~~

     

    第二步:下载预训练模型。

    facenet提供了两个预训练模型,分别是基于CASIA-WebFace和MS-Celeb-1M人脸库训练的,不过需要去谷歌网盘下载,这里给其中一个模型的百度网盘的链接:链接: 预训练模型百度网盘地址 密码: 12mh

    下载完成后,把预训练模型的文件夹拷贝在刚才的文件夹里。用pycharm打开这个工程文件如图:

     

     

    第三步:运行人脸比对程序(compare.py)。

    facenet可以直接比对两个人脸经过它的网络映射之后的欧氏距离。 

    -1、在compare.py所在目录下放入要比对的文件1.png和2.png。
    -2、运行compare.py文件,但是会报错如下:

    这是因为这个程序需要输入参数,在上方的工具栏里选择Run>EditConfigurations ,在Parameters中配置参数:20170512-110547 1.png 2.png。再次运行程序

     

    可以看到,程序会算出这两个图片的差值矩阵

     

    第四步:图片预处理——运行人脸对齐程序(align\align_dataset_mtcnn.py)。

    我们可以下载LFW数据集用来测试这个程序,也为后边的训练函数做好数据准备。

    下载链接:http://vis-www.cs.umass.edu/lfw/。下载后解压在data文件夹中。

     

    因为程序中神经网络使用的是谷歌的“inception resnet v1”网络模型,这个模型的输入时160*160的图像,而我们下载的LFW数据集是250*250限像素的图像,所以需要进行图片的预处理。

    在运行时需要输入的参数:

    input_dir:输入图像的文件夹(E:\facenet\data\lfw E:\facenet\data\lfw)

    output_dir:输出图像的文件夹(E:\facenet\data\lfw E:\facenet\data\lfw_160)

    指定裁剪后图片的大小:--image_size 160 --margin 32 --random_order(如果不指定,默认的裁剪结果是182*182像素的)

    比如我的是:E:\facenet\data\lfw E:\facenet\data\lfw_160 --image_size 160 --margin 32 --random_order

    如果在pycharm中运行,按照同样的方法配置以上参数如下:

     

    第五步:运行训练程序:(train_tripletloss.py)。

    前边已经下载并处理好了LFW的数据集,现在,可以进行训练了。

    运行之前,要在train_tripletloss.py中把加载数据的路径改成自己的数据集所在路径,如下图:

     

     

    注:train_tripletloss.py和train_softmax.py的区别:这是作者对论文做出的一个延伸,除了使用facenet里提到的train_tripletloss三元组损失函数来训练,还实现了用softmax的训练方法来训练。当然,在样本量很小的情况下,用softmax训练会更容易收敛。但是,当训练集中包含大量的不同个体(超过10万)时,最后一层的softmax输出数量就会变得非常大,但是使用train_tripletloss的训练仍然可以正常工作。

     

    更多内容参见:史上最全的FaceNet源码使用方法和讲解(二)

     

    最后,附上原来的文件中各py文件的作用(持续更新):

     

    一、主要函数

    align/ :用于人脸检测与人脸对齐的神经网络

    facenet :用于人脸映射的神经网络

    util/plot_learning_curves.m:这是用来在训练softmax模型的时候用matlab显示训练过程的程序

     

    二、facenet/contributed/相关函数:

    1、基于mtcnn与facenet的人脸聚类

    代码:facenet/contributed/cluster.py(facenet/contributed/clustering.py实现了相似的功能,只是没有mtcnn进行检测这一步

    主要功能:

    ① 使用mtcnn进行人脸检测并对齐与裁剪

    ② 对裁剪的人脸使用facenet进行embedding

    ③ 对embedding的特征向量使用欧式距离进行聚类

     

    2、基于mtcnn与facenet的人脸识别(输入单张图片判断这人是谁)

    代码:facenet/contributed/predict.py

    主要功能:

    ① 使用mtcnn进行人脸检测并对齐与裁剪

    ② 对裁剪的人脸使用facenet进行embedding

    ③ 执行predict.py进行人脸识别(需要训练好的svm模型)

     

    3、以numpy数组的形式输出人脸聚类和图像标签

    代码:facenet/contributed/export_embeddings.py

    主要功能:

    ① 需要对数据进行对齐与裁剪做为输入数据

    ② 输出embeddings.npy;labels.npy;label_strings.npy

     

    个人知乎主页地址:知乎个人主页,主要写大数据分析,机器学习等相关系列文章,还有一些新发布科技产品的思考,欢迎关注。

    展开全文
  • FaceNet--Google的人脸识别

    万次阅读 多人点赞 2015-06-29 21:39:22
    贡献出FaceNet再刷LFW上人脸验证的效果新高 FaceNet与其他的深度学习方法在人脸上的应用不同,并没有用传统的softmax的方式去进行分类学习,然后抽取其中某一层作为特征,而是直接进行端对端学习一个从图像到欧式...

    引入

    随着深度学习的出现,CV领域突破很多,甚至掀起了一股CV界的创业浪潮,当次风口浪尖之时,Google岂能缺席。特贡献出FaceNet再次刷新LFW上人脸验证的效果记录。

    本文是阅读FaceNet论文的笔记,所有配图均来自于论文。
    转载请注明:http://blog.csdn.net/stdcoutzyx/article/details/46687471

    FaceNet

    与其他的深度学习方法在人脸上的应用不同,FaceNet并没有用传统的softmax的方式去进行分类学习,然后抽取其中某一层作为特征,而是直接进行端对端学习一个从图像到欧式空间的编码方法,然后基于这个编码再做人脸识别、人脸验证和人脸聚类等。

    FaceNet算法有如下要点:

    • 去掉了最后的softmax,而是用元组计算距离的方式来进行模型的训练。使用这种方式学到的图像表示非常紧致,使用128位足矣。
    • 元组的选择非常重要,选的好可以很快的收敛。

    先看具体细节。

    网络架构

    大体架构与普通的卷积神经网络十分相似:

    在这里插入图片描述

    如图所示:Deep Architecture就是卷积神经网络去掉sofmax后的结构,经过L2的归一化,然后得到特征表示,基于这个特征表示计算三元组损失。

    目标函数

    在看FaceNet的目标函数前,其实要想一想DeepID2和DeepID2+算法,他们都添加了验证信号,但是是以加权的形式和softmax目标函数混合在一起。Google做的更多,直接替换了softmax。

    在这里插入图片描述

    所谓的三元组就是三个样例,如(anchor, pos, neg),其中,x和p是同一类,x和n是不同类。那么学习的过程就是学到一种表示,对于尽可能多的三元组,使得anchor和pos的距离,小于anchor和neg的距离。即:

    在这里插入图片描述

    所以,变换一下,得到目标函数:

    在这里插入图片描述

    目标函数的含义就是对于不满足条件的三元组,进行优化;对于满足条件的三元组,就pass先不管。

    三元组的选择

    很少的数据就可以产生很多的三元组,如果三元组选的不得法,那么模型要很久很久才能收敛。因而,三元组的选择特别重要。

    当然最暴力的方法就是对于每个样本,从所有样本中找出离他最近的反例和离它最远的正例,然后进行优化。这种方法有两个弊端:

    • 耗时,基本上选三元组要比训练还要耗时了,且等着吧。
    • 容易受不好的数据的主导,导致得到的模型会很差。

    所以,为了解决上述问题,论文中提出了两种策略。

    • 每N步线下在数据的子集上生成一些triplet
    • 在线生成triplet,在每一个mini-batch中选择hard pos/neg 样例。

    为了使mini-batch中生成的triplet合理,生成mini-batch的时候,保证每个mini-batch中每个人平均有40张图片。然后随机加一些反例进去。在生成triplet的时候,找出所有的anchor-pos对,然后对每个anchor-pos对找出其hard neg样本。这里,并不是严格的去找hard的anchor-pos对,找出所有的anchor-pos对训练的收敛速度也很快。

    除了上述策略外,还可能会选择一些semi-hard的样例,所谓的semi-hard即不考虑alpha因素,即:

    在这里插入图片描述

    网络模型

    论文使用了两种卷积模型:

    • 第一种是Zeiler&Fergus架构,22层,140M参数,1.6billion FLOPS(FLOPS是什么?)。称之为NN1。
    • 第二种是GoogleNet式的Inception模型。模型参数是第一个的20分之一,FLOPS是第一个的五分之一。
    • 基于Inception模型,减小模型大小,形成两个小模型。
      • NNS1:26M参数,220M FLOPS。
      • NNS2:4.3M参数,20M FLOPS。
    • NN3与NN4和NN2结构一样,但输入变小了。
      • NN2原始输入:224×224
      • NN3输入:160×160
      • NN4输入:96×96

    其中,NNS模型可以在手机上运行。

    其实网络模型的细节不用管,将其当做黑盒子就可以了。

    数据和评测

    在人脸识别领域,我一直认为数据的重要性很大,甚至强于模型,google的数据量自然不能小觑。其训练数据有100M-200M张图像,分布在8M个人上。

    当然,google训练的模型在LFW和youtube Faces DB上也进行了评测。

    下面说明了多种变量对最终效果的影响

    网络结构的不同

    在这里插入图片描述
    在这里插入图片描述

    图像质量的不同

    在这里插入图片描述

    最终生成向量表示的大小的不同

    在这里插入图片描述

    训练数据大小的不同

    在这里插入图片描述

    对齐与否

    在LFW上,使用了两种模式:

    • 直接取LFW图片的中间部分进行训练,效果98.87左右。
    • 使用额外的人脸对齐工具,效果99.63左右,超过deepid。

    总结

    • 三元组的目标函数并不是这篇论文首创,我在之前的一些Hash索引的论文中也见过相似的应用。可见,并不是所有的学习特征的模型都必须用softmax。用其他的效果也会好。
    • 三元组比softmax的优势在于
      • softmax不直接,(三元组直接优化距离),因而性能也不好。
      • softmax产生的特征表示向量都很大,一般超过1000维。
    • FaceNet并没有像DeepFace和DeepID那样需要对齐。
    • FaceNet得到最终表示后不用像DeepID那样需要再训练模型进行分类,直接计算距离就好了,简单而有效。
    • 论文并未探讨二元对的有效性,直接使用的三元对。

    参考文献

    [1]. Schroff F, Kalenichenko D, Philbin J. Facenet: A unified embedding for face recognition and clustering[J]. arXiv preprint arXiv:1503.03832, 2015.

    更多内容欢迎关注公众号【雨石记】

    watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3hpbnpoYW5neWFueGlhbmc=,size_16,color_FFFFFF,t_70#pic_center
    展开全文
  • 人脸识别(Facenet

    万次阅读 多人点赞 2018-01-25 15:20:23
    人脸识别是目前应用非常广泛的一种生物识别技术,与其他生物识别技术(指纹识别,掌形识别,眼虹膜识别和声音识别)相比,人脸识别具有以下优势: 其他每种生物识别方法都需要一些人的配合动作,而人脸识别...
  • FaceNet

    2020-03-06 10:45:32
    FaceNet 摘要 本文主要介绍一种叫FaceNet的方法,用于将人脸从图片映射到一个欧式空间中, 可以通过向量的欧式距离来确定人脸相似度。文中方法使用深度卷积网络,训练过程中直接优化embedding,而不是调整...
  • FACENET

    2019-06-25 22:42:04
    facenet代码运行 1 将代码复制到如下路径 2 设置环境变量 3 解决ModuleNotFoundError: No module named 'align.detect_face'的报错 解决办法:将alian文件夹更名为my_align,并将相应的代码进行修改。 ...
  • facenet

    2020-03-14 15:39:06
    mtcnn+FaceNet 安装requirements.txt依赖 pip install -r requirements.txt 下载预训练模型: facenet提供了两个预训练模型,分别是基于CASIA-WebFace和MS-Celeb-1M人脸库训练的,不过需要去谷歌网盘下载,这里给...
  • Facenet

    万次阅读 2017-11-10 17:20:05
    论文:FaceNet: A Unified Embedding for Face Recognition and Clusterin
  • 基于FACENET的高精度人脸识别 一:项目展示: - 这是实时视频读取的展示,是可以读单张图片,或者本地视频流,抑或是实时人脸检测与分类的,至于我为什么不展示我的自拍,主要原因是因为太丑了hhhh 本文中我吧我...
  • 搭建人脸库 选择的方式是从百度下载明星照片 照片下载,downloadImageByBaidu.py # coding=utf-8 """ 爬取百度图片的高清原图 """ import re import sys import urllib import os...
  • 人脸识别facenet代码实现

    万次阅读 多人点赞 2018-05-23 21:33:02
    上一篇博文介绍了facenet的原理,这篇讲解一下代码的实现,对于facenet的代码目前也有写好的部分。具体见链接facenet代码实现 。大家可以通过git直接下载代码,然后运行里面的validata_on_lfw.py。输入对应的lfw...
  • 说明: 这是优达学城的一个机器学习作业项目, 我觉得还比较典型综合了几个常见的深度学习技术,值得分享一下;实现包括,数据增广,迁移学习,网络...项目3:人脸识别 欢迎来到机器学习工程师纳米学位的第三个项...
  • 技术:FaceNet、MTCNN 2、设计方案 ①设计与实现思路 第一步是获得可用于身份认证的人脸图像,并处理图片,解决不同光照条件导致的差异和其他差异;第二步是人脸检测,就是给一幅图像,找出图像中所有人脸的位置,...
  • TensorFlow MTCNN facenet 实现人脸识别

    千次阅读 2019-01-10 09:33:20
    MTCNN用于检测出图片中的人脸facenet用于识别人脸是谁。 一、整体思路 1 创建被识别目标的样本数据集。 这里我们选用刘翔和周杰伦来作为被识别的对象,因此,选取刘翔和周杰伦来作为基础的样本,提取出两者的...
  • Google人脸识别系统Facenet paper解析

    千次阅读 2018-03-27 23:50:48
    Facenet paper地址 : facenet; 论文解析下载地址(PDF版):论文解析FaceNet: A Unified Embedding for Face Recognition and Clustering Abstract摘要 Despite significantrecent advances in the field of ...
  • 人脸识别其实又分为两部分,人脸检测和人脸识别,在本次博客中,人脸检测使用MTCNN模型,然后利用facenet进行人脸识别。 Github链接:https://github.com/ALittleLeo/FaceRcognization/tree/master 觉得有用的话请...
  • 人脸检测MTCNN和人脸识别Facenet(附源码)

    万次阅读 多人点赞 2018-12-05 10:51:54
    原文链接:人脸检测MTCNN和人脸识别Facenet(附源码) 在说到人脸检测我们首先会想到利用Harr特征提取和Adaboost分类器进行人脸检测(有兴趣的可以去一看这篇博客第九节、人脸检测之Haar分类器),其检测效果也是不错的...
  • 人脸识别网络facenet原理

    千次阅读 2019-12-26 10:04:48
    人脸检测和人脸识别。人脸检测: 人脸检测就是获取图像中所有人脸的位置,并对人脸进行对齐。由于原始图像中的人脸可能存在姿态、位置上的差异,我们需要在获取人脸位置后,检测人脸中的关键点,根据这些关键点将人脸...
  • 在说到人脸检测我们首先会想到利用Harr特征和Adaboost分类器进行人脸检测,其检测效果也是不错的,但是目前人脸检测的应用场景逐渐从室内演变到室外,从单一限定场景发展到广场、车站、地铁口等场景,人脸检测面临的...
  • 人脸识别facenet原理

    千次阅读 2018-05-23 18:25:40
    facenet是谷歌提出的一种新的人脸识别的方法,该方法在LFW数据集上的准确度已经达到了99.6%,目前是该数据集上检测的最好记录。关于facenet的官方介绍看链接论文地址 。  facenet 不同于传统的CNN方法。传统的CNN...
  • 这篇博客的内容关于本人在实现人脸识别系统过程中的一些总结以及感悟,这其中包括部分源自Google的Facenet的源码解读、个人在实现人脸识别时的一些思路以及部分代码片等内容。 整体思路 参考论文 主要考了以下两篇...
  • 上一篇文章介绍了facenet人脸识别的源码使用,这篇文章就来搭建自己的人脸识别库。 1. 制作自己的人脸识别库 1.1 准备数据集 通过百度图片爬取一些明星图片为例,这里准备了一个DownloadImageByBaidu.py文件用来...
  • MTCNN与facenet实现实时人脸识别

    千次阅读 热门讨论 2018-12-05 21:59:55
    MTCNN+facenet实现实时人脸识别整体思路步骤1--框架搭建步骤2--人脸数据库构造步骤3--训练SVM分类器步骤4--实时人脸检测识别 整体思路 利用MTCNN进行人脸框提取,将提取后的人脸框送入facenet中提取出embedding,...
  • 本文开发的是一个完整的视频流人脸识别系统,主要流程如下: 首先,通过openCV抓取摄像头的视频流 第二,通过MTCNN对每帧图片进行人脸检测和对齐,当然考虑到效率我们可以每n个间隔帧进行一次检测 第三,通过...
  • 睿智的目标检测15——Keras 利用mtcnn+facenet搭建人脸识别平台学习前言什么是mtcnn和facenet1、mtcnn2、facenet整体实现代码实现流程一、数据库的初始化二、实时图片的处理1、人脸的截取与对齐2、利用facenet对矫正...
  • facenet 人脸识别原理理解(三)

    千次阅读 2019-03-11 17:43:19
    在前两篇文章已经介绍了facenet人脸识别代码的使用和具体操作,但相关的原理还是没有说,这篇文章进行简单的讲解一下。 1. 原理 在人脸识别中,当我们需要加在图片数据库入新的一张人脸图片时,是怎么做到识别的呢...
  • 基于mtcnn和facenet人脸识别,已经试验过了,可以直接运行
  • 最近接触了tensorflow和facenet人脸识别,用pip安装第三方库的时候安装了tensorflow和facenet,但是在安装facenet时发现也要安装tensorflow,想问下大佬这两个有什么区别,主要都分别来干什么的?是不是facenet...
  • 基于facenet人脸识别设计文档 一、概述 在Ubuntu系统上,创建人脸库搭建基于facenet的人脸识别库,本文采用Python从百度下载明星照片,通过facenet的检测对齐人脸函数制作人脸库,并使用facenet做人脸识别。 二、...

空空如也

1 2 3 4 5 ... 20
收藏数 99,386
精华内容 39,754
关键字:

facenet