如何快速搭建自己的人脸识别系统

文章目录

  • 前言
  • 一、原理介绍
    • 1.mtcnn
      • P-Net(Proposal Network)
      • R-Net(Refine Network)
      • O-Net (Output Network)
    • 2. facenet
    • 3. SVM(Support Vector Machine)
  • 二、人脸识别实现
    • 1.准备工作
      • 引入mtcnn
      • 下载facenet的权重文件:
      • 安装sklearn
    • 2.训练和预测
      • 数据准备
      • 训练
      • 预测
      • 识别结果
  • 总结
  • 参考


前言

如何快速搭建自己的人脸识别系统_第1张图片

如何用人工"智障"快速的识别人脸呢?首先我们拿到一张图片,需要去看看图片中是否有人脸,如果有人脸,我们需要把人脸截取出来,放入到特征提取网络中去提取特征,再把提取好的特征向量进行分类,这样就实现人脸识别了。是不是也没有想象中的那么难呢?
如何快速搭建自己的人脸识别系统_第2张图片
本篇博客使用mtcnn作为人脸定位的网络,facenet作为特征提取网络,使用svm作为分类器,将facenet提取到的128维特征向量,用于训练svm,通过svm实现人脸的识别。这样简单的人脸识别系统就完成了。
如何快速搭建自己的人脸识别系统_第3张图片
接下来我会简要的介绍一下,mtcnn ,facenet 和svm的原理。

附上资源链接:
项目完整:https://pan.baidu.com/s/1rmRItADJdwvCQrC3TNPwRQ
提取码:gwto
GitHub地址:https://github.com/jiantenggei/face_recognization

一、原理介绍

我们是站在巨人的肩膀上,完成自己的任务,mtcnn和facenet使用别人已经预训练好的网络模型,我们只训练svm。

1.mtcnn

mtcnn (Multi-task convolutional neural network,多任务卷积神经网络),将人脸区域检测和关键点检测放在了一起,检测的关键掉包括眼睛,鼻子,嘴角,五个关键点。
在这里插入图片描述
我们来看一下他的工作流程:
如何快速搭建自己的人脸识别系统_第4张图片

首先呢,将原图裁剪成不同的尺寸,再resize成12*12,再输入到P-Net中。

P-Net(Proposal Network)

如何快速搭建自己的人脸识别系统_第5张图片
P-Net的网络结构如上图所示,通过浅层的全卷积网络来获得Bounding-Box回归向量,并使用NMS(非极大值抑制)进行大部分窗口的过滤,

R-Net(Refine Network)

如何快速搭建自己的人脸识别系统_第6张图片
图片经过P-Net之后,会产生很多的预测窗口,将预测窗口全部送入到R-Net中,通过R-Net后,会消除掉质量很差的候选框,最后对剩下的候选框进行 Bounding-Box回归和NMS进一步优化预测结果。最后将输出较为可信的区域给O-Net。

O-Net (Output Network)

如何快速搭建自己的人脸识别系统_第7张图片
这一层会产生更细致的人脸信息,最后还回产生5个关键点landmark。

2. facenet

facenet 是谷歌提出的人脸算法,提出cnn+triplet loss mining的方法,在在LFW数据集上,准确率为0.9963,在YouTube Faces DB数据集上,准确率为0.9512。我们来看一下facenet的网络结构:
如何快速搭建自己的人脸识别系统_第8张图片
DEEP ARCHITECTURE 是一个卷积网络,它可以是Mobilenet或者是ResnetV1,主要作用就是用于特此区域 在通过L2正则化,再embeding成一个128维的向量,再用triplet loss计算损失。但再实际的训练中,还要引入一个优化器来帮助网络收敛。
如何快速搭建自己的人脸识别系统_第9张图片
facenet是将人脸特征映射到128维的特征空间中,然后通过计算欧式距离来判断分类。上图就是triplet loss的学习过程。

3. SVM(Support Vector Machine)

SVM 支持向量机,将facenet提取到的128维的特征向量,输入到支持向量机中进行训练,用支持向量机来做分类判断。那有人可能就要问了,为什么不在facenet后之间链接全连接层来做分类呢。因为这样的做的话,需要训练的参数会很多,如果你要去识别1w个人 那么参数就是128*1w。如果每个人只提供的图片不多。那么网络是很难训练的。对于支持向量机,则需要很少的训练数据,就可以达到一个还不错的效果。支持向量机是将低维线性不可分的向量,映射到高维可分。介绍玩原理,我们可以来看如何实现的了。

二、人脸识别实现

1.准备工作

引入mtcnn

下载链接:https://github.com/ipazc/mtcnn
如何快速搭建自己的人脸识别系统_第10张图片
将图中的文件夹下载后放入工程目录中。或者直接使用pip 安装:

pip install mtcnn

要求OpenCV>=4.1 Keras>=2.0.0
先面试测试mtcnn的一段代码:

from mtcnn import MTCNN
import cv2
test_img = cv2.imread("imgs/img.png")
detector = MTCNN()
result=detector.detect_faces(test_img)
print(result[0]['box'])
for item in result:
    x,y,width,height = item['box']
    confidence=item['confidence']
    confidence=round(confidence,3)
    test_img = cv2.rectangle(test_img,(x,y),(x+width,y+height),color=(0,255,0),thickness=2)
    test_img = cv2.putText(test_img,str(confidence),(x,y-10),color=(0,0,255),fontScale=3,fontFace=cv2.FONT_HERSHEY_PLAIN,thickness=2)

cv2.imshow('img',test_img)
cv2.waitKey()

运行结果:

下载facenet的权重文件:

下载链接:https://pan.baidu.com/s/1DC929csx8Vtadbuk7YNTCw 提取码:atdf
放入到工程的weights目录下:
在这里插入图片描述

安装sklearn

pip install sklearn -i https://pypi.tuna.tsinghua.edu.cn/simple 

这里我们使用sklearn机器学习框架。

2.训练和预测

数据准备

首先我们将需要识别的人的照片,放入到以他们名字命名的目录下,用英文进行命名。如下图所示:如何快速搭建自己的人脸识别系统_第11张图片
照片中必须只包含识别对象的单一人脸,如下图:

下面是不合法图片:
如何快速搭建自己的人脸识别系统_第12张图片

训练

训练过程如下图所示:
如何快速搭建自己的人脸识别系统_第13张图片
SVM模型保存成pkl文件。
我们这里主要看训练SVM的过程,其他步骤的代码在github中会展示。

from sklearn.metrics import accuracy_score
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import LabelEncoder  # 将离散的数据转换到0~classes-1
from sklearn.preprocessing import Normalizer
from sklearn.svm import SVC
from get_feature import get_feature
import pickle

def train():
	#过去特征和对应的标签,有
    X_train, y_train, X_test, y_test = get_feature() 
    print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)
    # 样本的特征值除以个特征值的平方和,归一化
    in_encoder = Normalizer()
    X_train = in_encoder.transform(X_train) #编码
    X_test = in_encoder.transform(X_test) #编码
    # lable_encoder
    out_encoder = LabelEncoder()
    out_encoder.fit(y_train)
    y_train = out_encoder.transform(y_train)
    y_test = out_encoder.transform(y_test)

	#定义支持向量机,使用线性核
    model = SVC(kernel='linear', probability=True)

    model.fit(X_train, y_train)

    # 预测,predict
    yhat_train = model.predict(X_train)
    yhat_test = model.predict(X_test)

    score_train = accuracy_score(y_train, yhat_train)
    score_test = accuracy_score(y_test,yhat_test)

    print('Accuracy: train=%.3f, test=%.3f' % (score_train * 100, score_test * 100))

    #模型的保存
    pkl_filename = "sklearn_model.pkl"
    with open(pkl_filename,'wb') as f:
        pickle.dump(model,f)

if __name__ == '__main__':
    train()

保存训练好的模型方便用于预测。

预测

预测过程和训练过程类似,如下图所示:
如何快速搭建自己的人脸识别系统_第14张图片
我们来看一下代码实现:

from sklearn.preprocessing import Normalizer
from extract_face.extract_face import extract_faces
import cv2
import pickle
from tensorflow.keras.models import load_model
import numpy as np
from get_feature import get_embedding, create_dict

# 预测跟训练类
# 1.打开摄像头,mtcnn获取人脸
# 2.facenet 计算特征向量
# 放入svm中进行分类 最后输出预测结果
dict = create_dict(r'data/train/')


def predict(image):
    global dict
    print(dict)
    face_list, boxes_list = extract_faces(image)
    if len(face_list) != 0:
        facenet_model = load_model('weights/facenet_keras.h5')
        emdTrainX = list()
        for face in face_list:
            emd = get_embedding(facenet_model, face)
            emdTrainX.append(emd)

        emdTrainX = np.asarray(emdTrainX)
        emdTrainX.reshape(-1, 1)
        in_encoder = Normalizer()
        X_train = in_encoder.transform(emdTrainX)
        pkl_filename = "sklearn_model.pkl"
        with open(pkl_filename, 'rb') as file:
            pickle_model = pickle.load(file)
        result_list = pickle_model.predict_proba(X_train)
        print(result_list)
        print(type(result_list))
        result_index = np.argmax(result_list, axis=1)
        print(result_list)
        index = 0
        for result in result_index:
            if result_list[index][result] <= 0.6:
                label = 'unkonw'
            else:
                label = dict[result]
            x, y, width, height = boxes_list[index]
            image = cv2.rectangle(image, (x, y), (x + width, y + height), color=(0, 255, 0), thickness=2)
            image = cv2.putText(image, str(label), (x, y - 10), color=(0, 0, 255), fontScale=1,
                                fontFace=cv2.FONT_HERSHEY_PLAIN, thickness=2)
            index += 1
    return image


if __name__ == '__main__':
    img = cv2.imread("imgs/7dec538286139700dc9f34e94048b85.jpg")
    predict(img)
    cv2.imshow('t', img)
    cv2.waitKey()

这里需要注意的是有一个置信度的判断,如果没有这个判断,那么识别的时候,如果识别对象不在你的人脸库,(假设人脸库中有两个人,一个是彭于晏,一个是胡歌),那么如果判别这个人有10%跟彭于晏相似,30%跟胡歌相似,那么就会把这个人识别为胡歌。我们需要在代码中添加一段如下代码:

  if result_list[index][result] <= 0.6:
                label = 'unknow'

如何识别的置信度小与0.6那么就判断为unknow。到此,简单的人脸识别系统就搭建完成了。
为了方便我使用tkinter写了一个简单的几面,如下图所示:
如何快速搭建自己的人脸识别系统_第15张图片
启动时启动摄像头进行识别,采集时使用摄像头采集图片,放入到训练集和测试集中,重新训练是采集完成后,重新训练是训练采集后的图片,让模型能够识别采集后的人。

识别结果


这是最终的识别结果,因为叛变这个人不在我们的人脸数据库总,所以识别为unknown。

总结

代码会上传到GitHub中,供大家学习和参考,实现整个系统后识别速度比较慢,可能是我显卡不太好的原因。深度学习有很多网络,来完成不同的任务,如果我们要投入应用中,需要选择一个合适的网络,然后通过更改和微调,使其准确率和速度能跟上我们的需求。总结不易,点赞鼓励。~

参考

https://zhuanlan.zhihu.com/p/130931317
https://zhuanlan.zhihu.com/p/337690783
https://blog.csdn.net/qq_36782182/article/details/83624357
https://blog.csdn.net/u014380165/article/details/78906898
https://zhuanlan.zhihu.com/p/30195134
https://arxiv.org/ftp/arxiv/papers/1604/1604.02878.pdf
https://www.jianshu.com/p/4236679aa3ac

你可能感兴趣的:(深度学习入门,人脸识别,计算机视觉,机器学习,python,人工智能)