除非比较重要的文章,其他小文章都放在52coding.com上了。此文属于,吐槽文章。
持续维护地址: http://52coding.com/kinect-face-recognition-development
本篇文章主要讲的是开发者的切身经历,如果你正在弄Kinect或者做系统,又或者曾经做过一段时间,或许会有所共鸣。如果要了解系统中使用的一些算法,我已经做了多篇博客,你可以很容易搜到,我只给文章名字不给链接了。《怎样使用OpenCV进行人脸识别》《Kinect Face Tracking SDK[Kinect人脸跟踪]》《Gabor的OpenCV代码》,都是无价的文章。
我是2011年暑假开始研究人脸识别,那时刚弄完本科的毕业设计---Haartraining人脸检测,当时haartraining整的挺火热的,农歌毕业不成问题。暑假来到上海的大学,开始研究生生涯。接到电话,说本科毕设的论文评上院优秀论文,不是校优,凑合吧,看来不论选择和什么老师做毕设,都是金子。
当时OpenCV没有FaceRecognizer模块,Kinect才接触,微软也只提供了简陋的Kinect SDK beta(没有人脸追踪)。我也只会个C++和Matlab,不过这些就够了。看阅各种人脸识别的书籍,图书馆所有和人脸识别的书都被我借过来。这还不够,打印了李子青Handbook of face reconition,以及购买了基本人脸识别的图书。研究OpenCV的C++接口,打印了OpenCV参考文档。上课看,回宿舍看,有时上厕所也看。
一开始为了熟悉Kinect,那时还是Kinect for Xbox,我做了一个动作识别系统,五千行代码,仿照国外C#的动作识别算法,弄过的都知道他们。什么,他们的算法好像就几百行,你的怎么这么复杂?我设计了复杂的数据结构,做了向后扩展,也就是说他如果明天说可以检测6个人的骨骼了,我代码不用修改都可以用,然后每过一段时间会自动清除消失的人物的骨骼数据(具体点,骨骼数据和动作识别数据),更加,我检测的动作也增加了。其中以前后左右上下方向的识别还是不错。
然后我就开始搭建人脸识别系统。首先开始设计的就是数据库,这块我用了整整1个月时间。不仅仅设计数据库吧,主要系统模型设计好,数据库怎么为以后的系统做准备。数据库使用最简单的Access,因为电脑普遍都支持容易配置,并且MFC支持不错。数据库代码约2000行左右,包含各种各样的功能。特别的是的,当时没有很好的考虑图像数据存储问题,所以设计的数据库是把图像数据一起存放进去的,这点为后来制造了不少麻烦。
技术发展迅速,渐渐出现了带有人脸识别模块的OpenCV,我很快学会使用它,并且翻译了那篇文章。看到他写的代码的质量和优美,感觉如诗如画。当时我自己用OpenCV写了PCA算法,又在弄LDA,但缺乏资料,这下它把他们都实现且封装了,我很是开心。可以直接学习,也可以直接使用。
因为Kinect只有骨骼追踪,没有人脸检测算法,我又在想办法弄Adaboost,发现准确率地啊。又去弄基于肤色的人脸检测算法,还没全弄好,Kinect说他提供人脸追踪功能。我去,弄了半天,没想到它突然出现啊,当时是2012年3月吧,它一出来(Kinect SDk1.5),我就速度用它分割了简陋的人脸图片。首先感觉,定位十分准确,比Adaboost准确多了,也会比没有完成的基于肤色分割的准确。其次,这个图像质量,能做人脸识别吗?质量比ORL、Yale等很老的数据库中的人脸差了不知道多少倍。好吧,微软说它在Xbox中实现了人脸识别,咱信任他的说法,自己干一个看看。
正为着这么低劣分辨率的图像发愁,Kinect for Windows横空出世,分辨率提高了一些。我知道,别想再等下去了,Kinect分辨率不会再提高了,是时候考虑采集人脸的事情。特别的现在SDK提供了录制功能,感觉微软就是为了我的毕设卖力开发啊,没有这些功能:人脸追踪、分辨率更高的Kinect for Windows还有录制功能,我看我的硕士课题玩不下去了。
正是处于Kinect和OpenCV的高速发展,我的人脸识别系统不断改进。我也一直一手更新Kinect和OpenCV更新的信息,分享自己掌握的知识,造福广大程序员。
2012的7月开始,用了整整一个暑假,才完成了人脸数据采集方案的制定和实施,麻烦了45个同学来配合,原本设计每个方向上(十来个方向划分)人脸图片起码得50张,运行程序发现有些同学不够,很多采集了2到3次。不错,有些同学的人脸真怪,Kinect就是很难捕获他的脸,囧。还有的同学头总是歪着的,并且怎么纠正都没用,真是奇葩,只能删掉他的数据,再找其他人充数。很多个夏天的下午,我就折腾数据采集了。数据采集后,还得进行人脸分割,将图像存放到数据库里,弄个系统,没数据库不像话。
数据库的设计:图像数据直接存在Access数据库中(MFC的ADO编程),不但用了大量代码进行读写,并且实际运行时读写速度慢的要死!没人指导,我又赶时间完成这个系统,硬着头皮将分割的人脸存到数据库里了。经常是这样的,运行程序(face tracking功能,可以参考那篇文章)分割人脸,分割后查看人脸数据是否可用(有的人脸没跟踪好,能删就删,反正图片多,有些错的不用在意),然后输入名称保存,这时就得等待漫长的时间。程序要写数据库,但很缓慢,数据存的越多越缓慢,很多时间我就刷网页了,哎。反正暑假那两个月煎熬。特别的,我分割的不但是rgb图像,而且还有深度图像的人脸。有人处理过深度图像吗?即使用了提供的转换,它的坐标竟然还是偏移的,你得自己修正。深度图像有孔洞?的确有,当时SDK还很多孔洞呢,你自己插值呗。后来SDK更新,解决了孔洞问题,囧,又白折腾了。之后,我将图片存放在磁盘中,数据库存放图片地址,才加快数据的读写,不过大量测试时,你快不到哪里去。谁叫我分割了12万张图像,6万彩色和6万深度图像,数据库那么长,每次不是简单的读取,还是读取后是自动打乱的,每次读的图像都不会相同。
数据库庞大,之后需要抽取图像进行训练,这时我又得考虑一些缓存方法,保存一些数据信息,减少它需要扫描数据库的时间。为什么需要扫描,因为,你不知道每个人的图片有多少张,每种朝向(自己将人脸姿态角度分类,模仿了PIE人脸数据库)有多少张,我们只有选择最小值才行。也就是说,你要拿某类的30张图像训练,那么每个人图像应该都得大于等于是把,然后每个人取得时候是随即获取他N个中的30张,如果写matlab自然简单,但你用c++得保证木有问题才能出现正确结果,够你折腾的吧。没有Image Watch,你不知道自己是否真的去读正确了。
各种算法的融合,首先你得了解那些算法比较好,你有什么资源,那些算法你可以实现?matlab确实有不少算法,你可以参照其中的代码,写出OpenCV版本的。比如我模仿了PCA、LDA、Gabor等等。预处理、特征提取和降维、分类,每一层,我都尝试各种算法进行多次随机测试。你得一个一个实现好,关键要处理的是数据如何传输?这时我的程序已经很大了,数据如何在各种类中传输,拷贝少、速度快都得考虑。需要使用多少张图像进行训练,你多试几次,电脑死掉了说明不行了。图像多大合适?你得考虑可能要用到傅里叶变换,最好是2、3、5的倍数为佳。Gabor卷积核多大合适?维数降到多大合适?你多次测试,统计时间和准确率看看。速度快,准确率会低,速度慢,耗时又长了。而且还带有随机性,因为我的训练集图片每次测试都是随机的,你得测5次吧,如果变化太大,测10次吧。
ok,你到这里弄了基于静止图像的人脸识别算法,写出来可以成本科毕设吧,研究生不太好。那我在整个多数投票方法吧,权值哪里来?刚才做的大量测试来。
你弄出来分类器,用图片弄那么长时间,实时运行效果行不行?你得测试,中间处理结果你得保存,处理结果你得显示。人物移出界面程序死掉、参数没设置好运行死掉、时间运行长了莫名其妙程序死掉、光照变化了效果不行了。
当然,一切优化的差不多了,用了很长时间与老师交流和修改,最终分数很低。只能说声,抱歉,虽然用了如此多的精力,与无数前人没有遇到的问题pk,我尽力了无悔了。
微博:http://weibo.com/1083488192/zCVUznJON