全部版块 我的主页
论坛 数据科学与人工智能 数据分析与数据科学 数据分析与数据挖掘
1334 0
2020-09-17
使用FaceNet建立人脸识别
人脸识别是两个主要操作的组合:人脸检测和人脸分类。在本教程中,我们将研究对象检测的特定用例-人脸识别。
有关项目的管道如下:
人脸检测:查看图像并找到其中所有可能的人脸
脸部提取:专注于每个脸部图像并理解它,例如,如果将其侧向旋转或光线不足
特征提取:使用卷积神经网络(CNN)从面部提取独特特征
分类器训练:最后,将面孔的独特特征与所有已知的人进行比较,以确定该人的名字
我们将学习每个步骤的主要思想,以及如何使用以下深度学习技术在Python中构建自己的面部识别系统:
dlib(http://dlib.net/):提供一个可用于面部检测和对齐的库。
OpenFace(https://cmusatyalab.github.io/openface/):一种深度学习的面部识别模型,由Brandon Amos等人(http://bamos.github.io/)开发。它也可以在实时移动设备上运行。
FaceNet(https://arxiv.org/abs/1503.03832):一种用于特征提取的CNN架构。对于损失功能,FaceNet使用三重损失。三重态损耗取决于最小化与阳性实例的距离,同时使与阴性实例的距离最大。
搭建环境
由于设置会变得非常复杂并且需要很长时间,因此我们将构建一个包含所有依赖项的Docker映像,包括dlib,OpenFace和FaceNet。
获取代码
从存储库中获取用于构建人脸识别的代码:
git clone https://github.com/PacktPublishing/Python-Deep-Learning-Projects cd Chapter10/
构建Docker映像
Docker是一个简化部署的容器平台。它解决了将软件依赖项安装到不同服务器环境中的问题。如果您不熟悉Docker,可以在https://www.docker.com/上阅读更多内容  。
要在Linux机器上安装Docker,请运行以下命令:
curl https://get.docker.com | sh
对于其他系统,例如macOS和Windows,请访问  https://docs.docker.com/install/。如果已经安装了Docker,则可以跳过此步骤。
安装Docker之后,您应该可以在终端中使用docker命令,如下所示:
现在,我们将创建一个docker文件,该文件将安装所有依赖项,包括OpenCV,dlib和TensorFlow。
#Dockerfile for our env setup
FROM tensorflow/tensorflow:latest
RUN apt-get update -y --fix-missing
RUN apt-get install -y ffmpeg
RUN apt-get install -y build-essential cmake pkg-config \                    libjpeg8-dev libtiff5-dev libjasper-dev libpng12-dev \                    libavcodec-dev libavformat-dev libswscale-dev libv4l-dev \                    libxvidcore-dev libx264-dev \                    libgtk-3-dev \                    libatlas-base-dev gfortran \                    libboost-all-dev \                    python3 python3-dev python3-numpy
运行apt-get install -y wget vim python3-tk python3-pip
WORKDIR / RUN wget -O opencv.zip https://github.com/Itseez/opencv/archive/3.2.0.zip \ &&解压缩opencv.zip \ && wget -O opencv_contrib.zip
https://github.com/Itseez/opencv_contrib/archive/3.2.0.zip \    && unzip opencv_contrib.zip
# install opencv3.2
RUN cd /opencv-3.2.0/ \  
&& mkdir build \  
&& cd build \  
&& cmake -D CMAKE_BUILD_TYPE=RELEASE \         
           -D INSTALL_C_EXAMPLES=OFF \
           -D INSTALL_PYTHON_EXAMPLES=ON \
           -D OPENCV_EXTRA_MODULES_PATH=/opencv_contrib-3.2.0/modules \
           -D BUILD_EXAMPLES=OFF \
           -D BUILD_opencv_python2=OFF \
           -D BUILD_NEW_PYTHON_SUPPORT=ON \
           -D CMAKE_INSTALL_PREFIX=$(python3 -c "import sys; print(sys.prefix)") \
           -D PYTHON_EXECUTABLE=$(which python3) \
           -D WITH_FFMPEG=1 \
           -D WITH_CUDA=0 \            .. \
    && make -j8 \
    && make install \
    && ldconfig \
    && rm /opencv.zip \
    && rm /opencv_contrib.zip  # Install dlib 19.4RUN wget -O dlib-19.4.tar.bz2 http://dlib.net/files/dlib-19.4.tar.bz2 \
    && tar -vxjf dlib-19.4.tar.bz2 RUN cd dlib-19.4 \
    && cd examples \
    && mkdir build \
    && cd build \
    && cmake .. \
    && cmake --build . --config Release \
    && cd /dlib-19.4 \
    && pip3 install setuptools \
    && python3 setup.py install \
    && cd $WORKDIR \
    && rm /dlib-19.4.tar.bz2   ADD $PWD/requirements.txt /requirements.txtRUN pip3 install -r /requirements.txt  CMD ["/bin/bash"]
现在执行以下命令来构建映像:
docker build -t hellorahulk/facerecognition -f Dockerfile
安装所有依赖项并构建Docker映像大约需要20-30分钟:
下载预训练的模型
我们将下载更多工件,这些工件将在本教程的后面部分中使用和详细讨论。使用以下命令下载Dlib的人脸标志预测器:
curl -O http://dlib.net/
files/shape_predictor_68_face_landmarks.dat.bz2
bzip2 -d shape_predictor_68_face_landmarks.dat.bz2
cp shape_predictor_68_face_landmarks.dat facenet/
下载预训练的初始模型:
curl -L -O https://www.dropbox.com/s/hb75vuur8olyrtw/Resnet-185253.pbcp Resnet-185253.pb预设模型/
准备好所有组件之后,文件夹结构应大致如下:
代码的文件夹结构
确保将要训练模型的人员的图像保存在/ data文件夹中,并将该文件夹命名为/data/<class_name>/<class_name>_000<count>.jpg。
/ output文件夹将包含训练有素的SVM分类器和/ intermediate子文件夹中的所有预处理图像,并使用与/ data文件夹相同的文件夹命名法。
为了在准确性方面获得更好的性能,建议为每个类别保留五个以上的图像样本。这有助于模型更快地收敛并更好地推广。
建立管道
面部识别是一种生物识别解决方案,可以测量面部的独特特征。要执行面部识别,您需要一种独特地代表面部的方法。任何人脸识别系统背后的主要思想是将人脸分解成独特的特征,然后使用这些特征来表示身份。
构建强大的特征提取管道非常重要,因为这将直接影响系统的性能和准确性。
为了构建人脸识别管道,我们将设计以下流程(在图中以橙色框表示):
预处理:查找所有面孔,固定面孔的方向
特征 提取:从处理过的面孔中提取独特特征
分类器 训练:训练具有128维特征的SVM分类器
此图像说明了人脸识别管道的端到端流程。我们将研究每个步骤,并构建我们世界一流的人脸识别系统。
图像预处理
我们开发流程中的第一步是人脸检测。然后,我们将对齐面部,提取特征,然后完成对Docker的预处理。
人脸检测
显然,首先定位给定照片中的面孔非常重要,这样才能将其输入到管线的后半部分。有很多检测脸部的方法,例如检测皮肤纹理,椭圆/圆形检测以及其他统计方法。我们将使用一种称为HOG的方法。
HOG是一种特征描述符,它表示用作特征的渐变方向(定向渐变)的分布(直方图)。图像的梯度(x和y导数)很有用,因为在边缘和拐角处(强度变化剧烈的区域),梯度的大小很大,这在给定图像中是极好的特征。
要在图像中查找人脸,我们将图像转换为灰度。然后,我们将一次查看图像中的每个像素,并尝试使用HOG检测器提取像素的方向。我们将使用dlib.get_frontal_face_detector()创建面部检测器。
以下小片段演示了实现中使用的基于HOG的面部检测器:
从skimage import io导入sysimport dlib  
# Create a HOG face detector using the built-in dlib classface_detector = dlib.get_frontal_face_detector()
# Load the image into an arrayfile_name = 'sample_face_image.jpeg'image = io.imread(file_name)
# Run the HOG face detector on the image data.
# The result will be the bounding boxes of the faces in our image.detected_faces = face_detector(image
# Loop through each face we found in the imagefor i
# Detected faces are returned as an object with the coordinates
# of the top
输出如下:
Found 1 faces.
-Face #1 found at Left: 365 Top: 365 Right: 588 Bottom: 588
对齐面
一旦知道了面部所在的区域,我们就可以执行各种隔离技术,从整体图像中提取面部。
要应对的挑战之一是图像中的脸部可能会朝不同的方向旋转,从而使它们看起来与机器不同。
为解决此问题,我们将使每个图像变形,以使眼睛和嘴唇始终位于所提供图像的样本位置。这将使我们在接下来的步骤中比较人脸变得容易得多。为此,我们将使用一种称为人脸界标估计的算法  。
基本思想是提出存在于每个面孔上的68个特定点(称为地标)-下巴顶部,每只眼睛的外侧边缘,每个眉毛的内侧边缘等。然后,我们将训练一种机器学习算法,以能够在任何面孔上找到这68个特定点。
下图显示了我们将在每个面上定位的68个地标:
此图像由在OpenFace(https://github.com/cmusatyalab/openface)上工作的Brandon Amos(http://bamos.github.io/)创建。
这是一个演示如何使用面部标志的小片段,我们在“ 设置 环境”部分中下载了该  片段:
import sys
import dlib
import cv2
import openface
predictor_model = "shape_predictor_68_face_landmarks.dat"
# Create a HOG face detector
face_detector = dlib.get_frontal_face_detector()
face_pose_predictor = dlib.shape_predictor(predictor_model)
face_aligner = openface.AlignDlib(predictor_model)
# Take the image file name from the command line
file_name = 'sample_face_image.jpeg'
# Load the image
image = cv2.imread(file_name)
# Run the HOG face detector on the image data
detected_faces = face_detector(image
# Loop through each face we found in the image
for i
# Detected faces are returned as an object with the coordinates   
# of the top
print("- Face #{} found at Left: {} Top: {} Right: {} Bottom: {}".format(i
# Get the the face's pose
pose_landmarks = face_pose_predictor(image
# Use openface to calculate and perform the face alignment
alignedFace = face_aligner.align(534
# Save the aligned image to a file
cv2.imwrite("aligned_face_{}.jpg".format(i)
使用此功能,我们可以在保留平行线的同时执行各种基本的图像转换,例如旋转和缩放。这些也称为仿射变换(https://en.wikipedia.org/wiki/Affine_transformation)。
输出如下:
通过分割,我们解决了在图像中找到最大脸的问题,并且通过对齐,我们根据眼睛和下唇的位置将输入图像标准化为居中。
这是来自我们的数据集的样本,显示了原始图像和处理后的图像:
特征提取
现在,我们已经对数据进行了细分和对齐,我们将生成每个标识的向量嵌入。然后可以将这些嵌入用作分类,回归或聚类任务的输入。
训练CNN以输出人脸嵌入的过程需要大量数据和计算机功能。但是,一旦对网络进行了训练,就可以生成任何脸部的测量结果,甚至是从未见过的测量结果!因此,此步骤只需要执行一次。
为了方便起见,我们提供了一个在Inception-Resnet-v1上经过预训练的模型,您可以在任何面部图像上运行该模型以获得128维特征向量。我们在“ 安装环境”  部分下载了此文件,该文件  位于/pre-model/Resnet-185253.pb目录中。
如果您想自己尝试此步骤,OpenFace提供了一个Lua脚本(https://github.com/cmusatyalab/openface/blob/master/batch-represent ...),该脚本将为文件夹中的所有图像生成嵌入并编写他们到一个CSV文件。
在段落之后可以找到为输入图像创建嵌入的代码。
在此过程中,我们将从Resnet模型中加载经过训练的组件,例如embedding_layer,images_placeholder和phase_train_placeholder以及图像和标签:
def _create_embeddings(embedding_layer
这是嵌入创建过程的快速视图。我们将图像和标签数据以及来自预训练模型的一些组件一起馈入:
该过程的输出将是128个维度的矢量,代表面部图像。
在Docker上执行
我们将在Docker映像上实施预处理。我们将项目目录作为卷挂载在Docker容器内(使用-v标志),然后对输入数据运行预处理脚本。结果将被写入使用命令行参数指定的目录中。
align_dlib.py文件来自CMU。它提供了检测图像中的面部,查找面部界标以及对齐这些界标的方法:
docker run -v $PWD:/facerecognition \
-e PYTHONPATH=$PYTHONPATH:/facerecognition \
-it hellorahulk/facerecognition python3 /facerecognition/facenet/preprocess.py \
--input-dir /facerecognition/data \
--output-dir /facerecognition/output/intermediate \
--crop-dim 180
在前面的命令中,我们使用--input-dir标志设置输入数据路径。该目录应包含我们要处理的图像。我们还使用--output-dir标志设置输出路径,该标志将存储分割后的对齐图像。我们将使用这些输出图像作为训练的输入。
--crop-dim标志用于定义图像的输出尺寸。在这种情况下,所有图像将以180×180的格式存储。此过程的结果将是在/ output文件夹内创建一个/ intermediate文件夹,其中包含所有预处理的图像。
训练分类器
首先,我们将从输入目录--input-dir标志中加载经过分割和对齐的图像。训练期间,我们将申请对图像进行预处理。该预处理将向图像添加随机变换,从而创建更多要训练的图像。
这些图像将以128的批量进给到预先训练的模型中。该模型将为每个图像返回128维嵌入,为每个批次返回128 x 128矩阵。创建完这些嵌入后,我们将把它们用作scikit学习SVM分类器中的特征输入,以训练每个身份。
以下命令将开始该过程,并训练分类器。分类器将作为泡菜文件转储到--classifier-path参数中定义的路径中:
docker run -v $PWD:/facerecognition \
-e PYTHONPATH=$PYTHONPATH:/facerecognition \
-it hellorahulk/facerecognition \python3 /facerecognition/facenet/train_classifier.py \
--input-dir /facerecognition/output/intermediate \
--model-path /facerecognition/pre-model/Resnet-185253.pb \
--classifier-path /facerecognition/output/classifier.pkl \
--num-threads 16 \
--num-epochs 25 \
--min-num-images-per-class 10 \
--is-train
--num-threads :根据CPU / GPU配置进行修改
--num-epochs :根据您的数据集进行更改
--min-num-images-per-class :根据您的数据集进行更改
--is-train :设置True标志进行训练
此过程将花费一些时间,具体取决于我们正在训练的图像数量。该过程完成后,我们将在/ output文件夹中找到一个classifier.pkl文件。
现在,您可以使用classifier.pkl文件进行预测,并将其部署到生产环境中。
评价
我们将通过执行以下命令来评估经过训练的模型的性能:
docker run -v $PWD:/facerecognition \
-e PYTHONPATH=$PYTHONPATH:/facerecognition \
-it hellorahulk/facerecognition \python3 /facerecognition/facenet/train_classifier.py \
--input-dir /facerecognition/output/intermediate \
--model-path /facerecognition/pre-model/Resnet-185253.pb \
--classifier-path /facerecognition/output/classifier.pkl \
--num-threads 16 \
--num-epochs 2 \
--min-num-images-per-class 10 \

关注 CDA人工智能学院 ,回复“录播”获取更多人工智能精选直播视频!


二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群