资源下载地址:https://download.csdn.net/download/sheziqiong/88268054
资源下载地址:https://download.csdn.net/download/sheziqiong/88268054

实时人脸识别

opencv+mtcnn+facenet+python+tensorflow 实现

前言:本文记录了在学习深度学习过程中,使用 opencv+mtcnn+facenet+python+tensorflow,开发环境为 ubuntu18.04,实现局域网连接手机摄像头,对目标人员进行实时人脸识别,效果并非特别好,会继续改进。当前时间距 facenet 论文发布已有三年,网上对于 facenet 的解读也有许多,但却也找不到什么能修修改改就能用的代码,所以本文就此而生,将会系统的介绍在 CNN 在图像识别方向-人脸识别,我会把我遇到的一切问题以及见解都陆续的补充在本文中,保证各位官人看的开心。

所用工具简介

  • opencv 很有名了,在本次项目中用到的当然是它的强大的图片处理能力了,大概就是读取、写入、连接手机摄像头一些了
  • mtcnn 是一个用来检测图片中人脸位置(人脸检测)的深度学习模型,其使用了三个卷积网络实现了对图像中人脸的检测,在文章后面再具体的介绍其实现的细节
  • facenet 是谷歌的一篇很有名的论文和开源项目,其实现了将输入的人像最终转换为 shape 为 1*128 的向量,然后通过计算不同照片之间的欧几里得距离来判断他们的相似度,当然其中还包含许多技巧以及创新的想法,最终的在 lfw(一个很有名的人脸数据库)准确率达到 99%+++,在文章的后面我会尽可能的解读其论文和代码中的有意思的想法
  • tensorflow 应该很熟悉了(不然你是怎么搜到我的这篇文章的?) 学习深度学习的应该都知道存在各种各样的方便于搭建网络的框架,tensorflow 就是其中很有名的一个,由 Google 开源,功能强大

opencv

连接手机摄像头,并通过其一些小函数,对图片进行一些简单的处理,手机上要下载一个 app ip摄像头

import cv2
video="http://admin:admin@192.168.0.107:8081/" #此处@后的ipv4 地址需要修改为自己的地址
# 参数为0表示打开内置摄像头,参数是视频文件路径则打开视频
capture =cv2.VideoCapture(video)

# 建个窗口并命名
cv2.namedWindow("camera",1)

# 用于循环显示图片,达到显示视频的效果
while True:
    ret, frame = capture.read()
    
    # 在frame上显示test字符
    image1=cv2.putText(frame,'test', (50,100), 
                cv2.FONT_HERSHEY_COMPLEX_SMALL, 2, (255, 0 ,0), 
                thickness = 2, lineType = 2)
                
    cv2.imshow('camera',frame)
    
    # 不加waitkey() 则会图片显示后窗口直接关掉
    key = cv2.waitKey(3)
    if key == 27:
        #esc键退出
        print("esc break...")
        break

    if key == ord(' '):
        # 保存一张图像
        num = num+1
        filename = "frames_%s.jpg" % num
        cv2.imwrite(filename,frame)

mtcnn

GitHub 上的 facenet 工程在实现 facent 的时候,为了便于测试,mtcnn 也一放在了工程文件中,在工程中的位置是 align/detect_face.py ,它的参数模型也保存在 align 文件夹下,分别是 det1.npy,det2.npy,det3.npy,它的用法便是先将网络搭建出来,定位 input 中的人脸的位置,然后返回自己设置的固定大小的脸部 crop,然后再将其输入 facenet 就 ok 了(作用就是人脸检测 + 定位 + 对齐,因为我们首要目的是让工程能跑起来,并且对其有一个大体的认识,这才方便后面的学习,具体的实现原理和代码解读,以及物体的检测发展历史,目前的发展方向,各种检测的算法,我会在文章的后面细说)

facenet

facenet.py 直接放在主目录下了,其主实现的功能是搭建网络,然后从模型中加载参数,接收固定大小的剪裁好的人脸照片,最终经过 embeding 层输出 1*128 的脸部特征向量,计算不同脸部照片的相似度时候直接计算向量的欧式距离就 ok 了,同一个人的照片,它们的差值比较小,不同的人差值会比较大,其中 facenet 最后使用的是 triplet loss 方法来微调 embeding(具体的论文算法,网络搭建,各种算法,以及代码解读我都放在文章的最后再说)

工程文件说明

目录结构

  • 20170512-110547 文件夹是 facent 的模型,官方存放在 Google 网盘上了(而且现在出来 2018 的预训练模型了),不方便下载的我一会儿会把用到的大文件打包放在坚果云上
  • align 文件中包含三个 mtcnn 要用到的模型,以及搭建 mtcnn 网络的文件 detect_face.py,这里面的东西在 facenet 的项目中的都可以找到
  • models 中存放的是训练好的 knn 模型,用于测试使用的简单模型,一会儿展示的效果也是由其完成
  • train_dir 顾名思义,就不解释了
  • facenet.py 就是一直在谈的东西,其中包含了如何搭建 facenet 网络,以及计算的内容
  • test.py train_knn.py temp_test.py imageconvert.py 这几个文件分别 人脸识别测试训练knn模型 遇到问题是精简代码调试使用图像批量转化 用于准备数据集 其他的没有谈及的文件都没有使用到,应该是以前测试时候忘记删除的

运行效果

这是使用手机摄像头拍摄 iPad 从网上随便搜来的合照进行测试(也许也不是随便搜的…),能够准确将人脸框出,并进行识别,因为我使用的是 knn 训练的,而这几个人是未经过特殊训练的,所以将其归结为未知人群,再接下来一段时间会对其进行改进,最终效果应该是可以实现单张图片数据库比对,这样就不用对需要识别的目标每一个都训练一遍了,这也是人脸识别要达到的效果,上面所说的 triplet loss 就是一种很好的方法

因为房间光线比较暗,用手机摄像头拍摄以前的自拍,识别成功

运行环境和运行说明

  • 推荐使用 Anaconda 配置 tensorflow 环境(因为本项目就是基于 tensorflow 框架的),是 CPU 版本(等新卡,其实就是穷…)网上教程很多,也很简单,本环境的 python 版本是 3.6 的,如果你的是 2.7 的话,那就要改很多东西了(跟着报错改就 ok),但何不如再安装个 3.6 的呢,在 anaconda 下真的是超级方便

  • 编辑器用的是 vscode,从 windows 转来,习惯使用 vscode,真的很好用,在安装 anaconda 的时候会提示你是否装个 vscode 的,当然使用其他的也很好

  • 一些依赖库当然是必备的,提示少啥装啥吧,我也忘了,反正那些基本的是要装的,比如 numpy maplotlib jupyter scikit-image librosa kersa 这些,安装也很简单,在 anaconda 里安装 使用 conda 命令 或者如果你的 Linux 的默认 python 就是 anaconda 里的,直接使用 pip 安装就好了

  • 本项目里的几个运行的代码,我都写好了参数,直接运行即可(当然制定文件要在指定位置) 运行顺序是

    • 准备好自己的训练集 几十张自己照片即可(尺寸要小一点的,最好 500*500 以下,不然速度慢,精度低),放到 train_dir/pic_me 文件夹下面,把我打包文件里的 pic_others 文件夹中的放到指定 train_dir/pic_others 下面(这部分数据也可以自己准备,我的数据是来自 lfw 中的前几百张图片)
    • 运行 train_knn.py 得到自己的 knn 模型
    • 运行 test.py (记得要把手机上的 ip 摄像头 app 打开,点击下面 打开IP摄像头服务器 ,并检查下显示的局域网 ip 和 test.py 中的是否相同,如不相同,改一下)
    • 启动的时候会比较慢,30s 到一分钟左右,取决于电脑性能

至此你应该已经成功跑起来这个项目了,在此感谢开源的伟大,让我们能感受到这些神奇的算法

阅读代码和重构项目建议

好学的各位爷肯定是要将代码好好看一通的,因为我也是菜鸡,看到拙劣之处,请会心一笑…

代码思路

  • 使用 mtcnn 截取视频帧中人像的人脸,并拉伸为固定大小(这里为 160*160,由使用的 facenet 网络所受限)
  • 将上一步骤得到的人脸输入 facenet,得到 embedding 层的输出,一个人像对应一个 1*128 数据,然后将其输入 knn 网络,得到预测结果

学习思路

  • 一定一定要搞清楚其中的数据流是以什么样的格式和形式在传递,其中大多数使用的都是 numpy.ndarray 数据类型,此外便要掌握一些基本的此类数据类型的格式转换函数,并熟记,很常用的,还有就是和 list 的转换
  • 掌握一点点 opcv 的读写函数
  • 掌握一些对文件操作的函数

更新

新增测试方法“直接使用 emb 特征进行计算对比”

此次更新主要想法

上一个版本是使用 knn 对准备好的若干张照片进行“训练”,首先准确率不是很高(还没细究问题,猜测原因是自己准备的图片问题,以及实时采集实时的环境影响),但最主要的原因还是对每个目标对象都必须准备若干张照片进行训练,再看当前市面上的人脸识别都是直接采集一张图片放入数据库,并不需要再训练,直接便可以识别,而 facenet 的最初思想便是如此,是一开始的自己走远了。

所以本次的更新便是,直接将想要测试的对象的一张照片以其英文名命名(中文会乱码),放入一个名为 test_img 文件夹中,接下来对其进行人脸检测并切割,切割后的人脸图片尺寸为 160*160,存入 emb_img 文件夹中,这一步的主要目的是为了不要每次测试的时候都还要重新开始人脸检测,当人脸识别程序启动时,先读取 emb_img 文件夹图片并输入网络得到其 emb(128 维特征),用于后续与摄像头捕捉的照片进行比较

总体来说,基本上没什么思想,可以说是很简单,甚至可以说是一个简单版的 knn,因为我的想法是以后能够将每张照片的 emb 存入数据库,并使用 kd 树优化(本次更新没有做),可是这样的话不就和 knn 一样了么,哎,做完自己才发现自己在做一件傻事,可是还是觉得 knn 不太好…先不管了,就酱

新增 两个文件夹两个.py文件

  • 文件夹(涉及个人和同学照片,未上传,测试时自己直接新建即可)

    test_img : 此文件夹中直接存放需要识别对象的一张照片

    emb_img: 此文件夹可以自己新建,或者不管(脚本中对这个文件夹检测了,没有则新建),用于存放剪切后的 160*160 尺寸的人脸图片

  • .py 文件(一个用来批处理图片,一个用来运行检测)

    calculate_dection_face.py : 代码中已经注明了有些路径自己要更改一下,先执行此脚本,进行人脸定位切割(有点残忍的感觉)

    new_face_recognition.py : 直接执行即可,此次默认使用的是电脑自带的摄像头(如果要使用手机的,自己改一下,还是以前方法),路径也要注意

注意事项

此次代码中的路径我使用的都是绝对路径,所以要根据自己的路径更改一下

资源下载地址:https://download.csdn.net/download/sheziqiong/88268054
资源下载地址:https://download.csdn.net/download/sheziqiong/88268054

更多推荐