基于OpenCV+dlib开发一个人脸识别应用

Python技术杂谈 2019-09-05 22:59:01 阅读(12493) 评论(0)

最近在做一个人脸识别的应用,Android系统的摄像头检测到人脸并识别出是谁。
这样一个系统看似简单,但架构比较复杂,移动设备本身的计算能力太弱,不能负担对计算力要求较高的人脸识别,因此,把人脸识别移到服务器端进行,Android客户端负责检测人脸和拍照,把图片传到服务器再进行人脸识别并返回结果。
架构清晰后就开始干起来了!

开发一个人脸识别小应用

Android Studio开发基于OpenCV的人脸监测

注意,这里是监测, 而不是检测,因为要求摄像头时刻开着,一有人脸跳进来就能马上检测到。
Android开发,俺也是做过的,五六年前吧。其实也只能说是小半只脚沾了点边儿,同事搭好的框架,我偶尔修改一些代码,对整个Android开发一知半解。那个时候开发工具都还是eclispe,Android的版本还是2或3吧。

而今,开发工具已经是Google自己发布的Android Studio(当然,eclipse还是能用的),编译工具是一个叫grable的东西。这个grable啊,给人的感觉真是慢啊,我的电脑24G内存,3.4GHZ的i7处理器,编译起来还是很慢啊。

工具都是新工具(其实即使还是eclipse,多年前的一知半解也早已化为云烟,跟新的又有神马区别呢?),语言也是新语言——JAVA。用Java也是那时候接触一点,基本上算是没有经验。还好有个OpenCV做Android开发的示例工程可以参考,谢天谢地,再这个基础上改就省了很多学习的事情。

人脸检测是在一个叫onCameraFrame()的方法里面去实现。这个方法就是在摄像头每一次获得一帧的时候需要干些什么?等等,每一帧?正常电影的视频好像是24帧每秒,摄像头也差不多吧。要是每一帧都做检测处理计算量很大啊,小小Android承受不起啊!于是每隔n帧做一次人脸检测,即使这样,出来的程序跑一会儿,手机就开始发烫了。

onCamerFrame()是在主线程另一个线程进行的,检测到人脸后还不能直接在主线程上进行UI操作,比如显示检测到人脸的信息。线程之间用消息传递来完成这个操作。一涉及到UI就很繁琐,不只是Android这样。

检测到人脸就拍个照片(当然是不经过磨皮的)传给服务器端进行识别。Android里面http请求、Json解析的代码还是很多的,能找到很多很多。不过对于Java语言的不熟就很费时,比如Vector的使用都要现学现用。

根据人脸识别年龄、性别、表情

这也是一个小需求,但是要真实现起来就很难了。好在大公司有现成的在线API可以调用。一番研究以后选了腾讯的优图。而且它还有Android上写好的Java库可用,值得一赞。但是那个例程比较乱。
识别出年龄、性别、表情等信息就要显示处理,那就弹个对话框吧。又遇到了线程和UI的问题。

服务器端基于dlib的人脸识别

基于dlib自己实现个人脸识别的服务吧,数据库记录已经被记住的人脸特征,来一张新脸时,先检测人脸和计算人脸特征,再与数据库进行对比,如果发现是已经被记住的脸,就返回跟老熟人打个招呼的消息。
Python用tornado开发个web服务很容易。基本上已经用tornado做了好多web服务器了,返回json数据,连网页都不用写。
dlib用人工神经网络进行人脸识别,计算量还是很大的,纯CPU计算一张人脸的特征要1.35秒左右,后来加了些编译参数,减小到1.2秒多。这点儿时间,反应到Android客户端上就是——感觉有点反应迟钝。以后实施还是上GPU好。

成品-Android应用(可试用)

以上开发已经完成,挑了些参数做了优化,随便起了个名字——哈哈看脸,请试用:
APP下载:http://ebuinfo.com/apk/app-face.apk
可选安装:讯飞语音+ , 百度搜索“讯飞语音+ 下载” 可以进行下载。安装后可以使得本应用能够语音播报。功能:

  • 启动APP后全屏显示前置摄像头的拍摄画面
  • 当有人脸被检测到时,会向服务器验证是否是老熟人(以前被记住过)
  • 如果不是熟人就向腾讯请求判别并显示年龄、性别、表情等信息
  • 如果是熟人就显示”您好,XXX”的文字,并语音问好(如果安装了讯飞语音+)

最后,记得不要玩这个太久,手机会发热的。

猿人学banner宣传图

我的公众号:猿人学 Python 上会分享更多心得体会,敬请关注。

***版权申明:若没有特殊说明,文章皆是猿人学 yuanrenxue.con 原创,没有猿人学授权,请勿以任何形式转载。***

说点什么吧...