人脸识别实践(1) - 基本原理与设计思路

写在前面

  随着时代的高速发展,视频监控等基础设施越来越完备,计算机视觉也在各行各业开始发挥出更大的效用,而这一领域中大家最熟知的就是刷脸支付,现在大家享受着科技带来的便利。还有我们乘坐高铁,进站前刷身份证然后脸对着摄像头,是本人才能够通过检票口,也用到了人脸识别技术。可见该技术存在着太多的应用场景。前段时间出现小区出现蜂巢的快递柜,它提供了人脸识别取快递的功能。最近在乘坐地铁的时候,发现现在过闸机也可以不用刷地铁卡直接人脸识别就通过了,我家这边地铁站的人脸识别设备是依图公司做的,这家公司在图像领域还是蛮有知名度的,还知道的一家比较出门的就是旷视,当然BAT也做,这里就不细说了。

  由于现在市面上人脸识别的应用越来越多,作为一名热衷于技术的IT男,我觉得有必要对人脸识别进行一个系统的了解学习和研究,深入的了解人脸识别的机制,是很有必要的。

  整个人脸识别的实现,我会用2-3个章节进行介绍,这个章节介绍思路和原理,后面的章节进行核心代码的讲解,后续会将代码放到github上归档,当然,这也是给自己一个代码整理的机会。

1. 整体设计思路

  首先对人脸识别的原理进行了解,通过代码来实现人脸识别相关算法的基本功能,在确认核心模块代码功能正常后,再考虑整个人脸识别管理平台如何设计。

  在人脸识别管理平台的设计上,梳理了需要完成的功能,一共包含人脸注册、人脸更新、人脸删除、人脸识别、人脸库查询这5个大功能的管理平台,同时考虑到每次程序运行后,在对人脸库进行修改后,需要保存这些录入的数据,所以还有个功能就是人脸数据的保存和读取。

1.1 人脸识别

  当用户在平台上传照片后,对照片上的人脸进行判断,如果人脸存在,那么使用人脸与程序中保存的人脸数据进行一对一的比较,每次比较的结果都保存起来,全部比较完成后,输出相似度最高的人脸库中的数据,同时将相似度也展示出来。

1.2 人脸注册

  当用户在平台上上传照片后,先对照片进行人脸检测,对于没有人脸和多于1个的,进行错误提示,因为人脸注册需要保证每次输入的user id能够对应到人脸库中具体的人的信息,只有当有且只有一个人脸的时候,才进行数据录入。

1.3 人脸更新

  用户输入存在的user_id后,上传照片,同样需要照片中的人脸只有一个,否则会提示人脸过多,更新失败,当满足条件后,对人脸特征进行获取后,保存在程序的人脸库中。

1.4 人脸删除

  ,当用户输入的user_id在我们库中存在的话,那么就删除这个人脸的信息的数据和照片,否则提示删除失败,数据信息不存在。

1.5 人脸库查询

  人脸库查询,提供一个输入框,可以输入需要查询的最大人脸个数,如果输入的数字大于人脸库中的个数,那么展示人脸库中的全部数据,包括user_id和照片,如果输入的数字大于人脸库中的个数,那就展示输入数字的个数的人脸的信息。

1.6 人脸数据的保存和读取

  考虑到这个系统不是每次打开都需要重新录入数据的,应该在程序关闭重新启动后,还要能读取原来保存的数据,否则每次都新增数据,不符合这个平台的功能。

  所以,在人脸注册、更新的时候,会讲照片保存在pic文件下,名字以user_id.jpg进行命名,在人脸删除的时候,除了删除内存中的数据之外,还要删除pic下的照片,这样相当于对数据进行了实时保存。

  程序启动的时候需要将人脸库的数据都读取到内存中,所以在程序启动的时候,需要去保存人脸照片的pic文件中,读取所有的user id.jpg图片,保存到人脸库中,这样,在程序启动的时候就能够保持和程序关闭前同样的状态了。

2. 人脸识别的基本原理

  人脸识别管理平台的开发,最为核心的技术就是人脸识别技术,所以这个章节重点进行理论基础的介绍。
要完成人脸识别功能,需要先读取图片进行人脸检测,通过检测到图片中的人脸后,获取人脸的68个特征点,再通过深度学习训练的模型,计算出人脸128个纬度的特征点,每个人脸都有自己的128维特征,当我们进行两个人脸的比对时,就可以通过对2个向量进行距离计算,根据计算的结果来判断人脸是否相似。

2.1 人脸检测器

  人脸检测基于成熟的图像处理技术dlib,首先我们需要对输入的图像进行人脸检测,dlib的人脸检测器是用经典直方图梯度特征和线性分类器、图像金字塔相结合,它使用了机器学习的方式创建了面部探测器。

2.2 人脸68个特征点

  通过人脸检测器完成人脸检测后,针对检测出来的每一张人脸,基于dlib使用英国伦敦帝国理工大学标注的300万人脸数据集结合计算机视觉技术训练的模型,通过模型shape_predictor_68_face_landmarks.dat推理出人脸的68个特征点,这些特征点包括了眉毛、眼睛、鼻子、嘴和面部轮廓,检测出来的结果如下图。

image

2.3 人脸128维向量

  根据68个人脸的特征点,使用dlib_face_recognition_resnet_model_v1.dat这个内置的深度学习模型,该模型在人脸识别标准测试集LFW上获得了99.38%的准确率,我在人脸识别中使用了该模型,输入68个人脸的特征点就能够推理出每个人脸的128维向量。

2.4 人脸相似度计算

  我们知道两个点之间的距离,可以使用以下公式进行计算:

ρ = ( x 2 − x 1 ) 2 + ( y 2 − y 1 ) 2 \rho = \sqrt{({x_2-x_1})^2+(y_2-y_1)^2} ρ=(x2x1)2+(y2y1)2

  ρ 为点(x2,y2)与点(x1,y1)之间的欧式距离。

  同理,三维空间的公式:

ρ = ( x 2 − x 1 ) 2 + ( y 2 − y 1 ) 2 + ( z 2 − z 1 ) 2 \rho = \sqrt{({x_2-x_1})^2+(y_2-y_1)^2+(z_2-z_1)^2} ρ=(x2x1)2+(y2y1)2+(z2z1)2

  n维空间的公式:

d ( x , y ) = ( x 1 − y 1 ) 2 + ( x 2 − y 2 ) 2 + . . . + ( x n − y n ) 2 d(x,y) = \sqrt{({x_1-y_1})^2+(x_2-y_2)^2+...+(x_n-y_n)^2} d(x,y)=(x1y1)2+(x2y2)2+...+(xnyn)2

  欧式距离就是n维空间中两个点之间的真实距离,这个可以判断向量之间的距离。对于128维的向量,属于更加大的一个空间,也可以使用欧式距离公式进行计算。

  但是我们需要对2个向量之间的距离有一个更加明显的认识,所以人脸识别中,一般会对欧式距离进行归一化,所以归一化后特征的余弦距离就是余弦相似度,我们就能使用相似度配置,在2个向量比较的时候,得到感受深刻的值,如果完全一样,那么值为1,如果很相似,余弦相似度为0.99等接近1的值,所以两个人脸越相似,那么他们的余弦相似度就越接近1。

3. 人脸管理平模块规划

  管理平台是B/S架构,程序启动后,通过网页访问人脸识别管理平台,通过浏览器中的操作,实现图片读取、图片编码、服务调用功能,在服务端来实现配置文件读取、http服务、图片保存功能。

3.1 前端设计

  由于平台除了提供给自己使用,还会提供给其他开发人员使用,参考了百度开放者平台上面的人脸识别管理平台,能看出他们使用了接口封装了人脸识别相关功能,所以参照他们的设计,我自己也仿照这种模式进行开发,使用了流行的前端框架VUE来进行前端开发工作。

3.2 图片读取

  前端的图片读取,直接使用了VUE封装的功能,能够打开本地图片文件。

3.3 图片编码

  读取图片后,将图片转码为base64编码,这样转化也是参考了百度接口的设计,将base64编码的图片文本数据为了发送到服务端进行处理。

3.4 图片保存

  服务端获取到base64编码的数据后,使用大家广泛运用的机器视觉库OpenCV将该编码的数据转为cv::Mat类型,提供给dlib进行人脸处理后,再通过大家熟知的base64编码转成图片文件,进行了文件的保存,统一保存成user id.jpg文件。

3.5 配置文件读取

  由于http服务需要提供端口进行访问,所以将端口配置到配置文件中,这样在程序启动的时候,就能够初始化端口,提供给大家访问。

  人脸识别也有一个相似度设置,所以也通过配置文件读取,这样如果要修改这个相似度,超过相似度才认为是同一个人,这样就不用改代码,只改文件,重启程序就可以实现了,更加的方便。

3.6 http服务

  为了提供公共的,大家熟知的接口,选取了和百度做的人脸识别一样的http接口,所以需要进行http服务端的开发,提供给web客户端进行调用。

3.7 写日志模块

  这个模块主要是为了方便调试,也方便真正使用过程中,如果出现了错误,还能够通过日志文件,查找定位问题,同时也能看到人脸识别的应用被访问的人调用了多少次,这样才能够为以后做大这个平台提供准备。

猜你喜欢

转载自blog.csdn.net/initiallht/article/details/122158268
今日推荐