闲来想完善一下之前做的汽车运动检测的工程,打算认认真真的将整辆车给识别出来,可是唯一的问题是,我手上没有足够的用来做训练的素材,于是从很流行的人脸识别开始,探求一下机器识别的流程如何。花了一些时间,在此作一下笔记。


一、使用TBB编译opencv_traincascade.exe


会跳到我这篇博文里来的童鞋,多是已经参考网上其他的文章,大概的流程估计已经知晓,文档式的内容我尽量少提。简单的提一下,视觉识别的过程主要是训练跟检测两项内容,此篇只讲训练。对基本素材的训练需要运用到opencv的两个自带的程序:opencv_createsamples.exe跟opencv_traincascade.exe(opencv_haartraining.exe据说是已经落后的东西就略过)。前者是用来用来准备训练用的正样本数据和测试数据,后者则是用来作训练用的,其具体介绍请自行google,我之所以要重新编译opencv_traincascade.exe,是因为opencv自带的程序不支持多核心运算,在跑了一个晚上后我坚决用TBB来重新编译,好让它支持cpu的多核性能。


使用TBB来编译opencv请参考这里,这篇文章的内容其实说得挺清楚的,但会有漏讲一些东西,像最后使用visual studio重新编译的时候会提示少了一些TBB的lib跟opencv的lib,少TBB的lib只需要在工程属性里添加库包含目录,少opencv的lib,则需要将提示缺少的lib全部拷贝一下就行(你实际操作的时候会清楚我说什么的啦)。然后你就可以在新编译出来的工程bin目录下看到支持TBB的opencv_traincascade.exe,我个人用的是VS2013编译的x64版本,我将其打包放到这里,可以提供给朋友们作训练测试。


其实效果挺明显,自带的opencv_traincascade作训练,程序的cpu占用率就25%,用我新编译的程序用训练cpu就暴到85%左右,今天用了一个半小时就训练完跑了之前要大半天的程序。(只是现在卡在stage 9那里,cpu占用率回到25%,程序到底有没有正常运行我很怀疑,但我用了7000张的图片,训练需要一定的耗时,也可能执行到不支持多核运算的步骤,跑到明天再见分晓吧。)


二、准备训练素材


(1)准备正负样本的图片素材


这是一个最重要的步骤,也是最痛苦的步骤,原来这世上是有这类东西的数据库的,经过几层跳转,我down到某个人脸识别的数据库(其原始链接我找不回来),正负样本共约7000的图片,因为ACDSee无法识别其格式,我又折腾地用PS批量转成了bmp格式,我放到这里供大家下载(见过这么用心的博主没?看过此文的人请多手点个赞吧。)什么叫正负样本?请自己google吧。


(2)编写正负样本描述文件


为方便管理,在C盘根目录下建一个文件夹(希望SSD会有点用),名为CvFile,将有正负样本的图片文件夹(分别叫face_bmp_2429、nonface_bmp_4548)放到里边去。在CvFile目录下新建个txt文件,起名叫face_2429_info.txt,如下面这么填内容:

//图片路径 数量 有效内容矩形信息
face_bmp_2429\face00001.bmp 1 0 0 19 19
face_bmp_2429\face00002.bmp 1 0 0 19 19
face_bmp_2429\face00003.bmp 1 0 0 19 19
face_bmp_2429\face00004.bmp 1 0 0 19 19
face_bmp_2429\face00005.bmp 1 0 0 19 19
...


内容可以用绝对路径的,为方便起见,要统一正样本的尺寸,“19 19”是图片的尺寸信息,这个很重要,这两个数据整个训练过程都要一致的。如果有人用自定义的素材,生成这个文本描述文件可以用命令行,也可以自己编代码来生成,请各自便(我是自己写了个程序,有需要的朋友问我要)。


负样本的描述文件就简单多了,同样新建一个叫non_face_4548_info.txt的文本文档,像以下这样编写就行,只需要写清楚路径就可以了。

//图片路径
nonface_bmp_4548\nonface0001.bmp
nonface_bmp_4548\nonface0002.bmp
nonface_bmp_4548\nonface0003.bmp
nonface_bmp_4548\nonface0004.bmp
nonface_bmp_4548\nonface0005.bmp
nonface_bmp_4548\nonface0006.bmp
...


一开始,我没找到样例,结果负样本的描述文件跟正样本弄成一样的,给果在训练时程序会提示“无效的背景描述文档(本是en文,忘了拼写)”,所以理论上负样本是不管图片大小的,只要满足“不包括目标物体的内容”这唯一条件即可。


(3)创建样本VEC文件


vec文件主要用于作训练用的,这是很关键的一个步骤,首先我们要找到opencv_createsample.exe这个程序,为省去麻烦,我是将opencv\build\x64\vc12\bin里的全部内容拷贝到CvFile文件夹里的,里面有opencv_createsample.exe这个文件。


使用命令行工具,定位到CvFile,启动opencv_createsample.exe,如下图输入命令:

opencv_createsamples.exe -vec pos.vec -info face_2429_info.txt -bg non_face_4548_info.txt -num 2429 -w 19 -h 19


成功运行会有如下图的提示:

OpneCV人脸识别:训练篇_第1张图片


命令的参数意义还是自己去查吧,关键的地方是-w -h两个参数须与正样本图片一致,CvFile文件下会生成一个pos.vec的文件,这就是接下来训练用的vec文件,那素材的准备就大功告成了。至于为什么我不用bat文件来启动程序,那是因为我没法为你们截图啊。


三、训练


好了,最让人关心的训练开始啦。先在CvFile新建一个文件夹mydata,这个是用来放cascade结果跟中间文件用的,网上很多教程没提这个事,否则会造成训练失败的。


同样使用cmd写下启动opencv_traincascade.exe程序的命令如下:

opencv_traincascade.exe -data mydata -vec pos.vec -bg non_face_4548_info.txt -numPos 2000 -numNeg 4000 -numStages 20 -featureType HAAR -w 19 -h 19 -mode ALL


需要注意几个参数,mydata就是上面新建的结果文件夹;-numPos及-numNeg的数值要比实际的样本数略小;-featureType有HAAR及LBP两种(HAAR - 类Haar特征; LBP - 局部纹理模式特征),前者是默认的,其区别请google,如果你想尽快看到训练结果可以将其设为LBP,其运行是相当快速的;-w -h参数则如我一直强调的,要通篇一致。正常运行如下图所示:

OpneCV人脸识别:训练篇_第2张图片


然后,就没有然后了,你就慢慢等训练结果出来吧,你可以查看mydata文件夹下的里的内容,等训练结束会存在cascade.xml的文件——这才是我们最终需要在检测用到的东西。个人太贪心,样本太多,stage数太多,现在一直卡在9-stage下,等出了结果我再写检测篇吧。