iOS开发之opencv学习笔记三:训练一套自己的特征库

上篇介绍了使用CascadeClassifier跟踪进行特定物体的跟踪

我们可以利用CascadeClassifier进行物体跟踪。其实,对特定物体的跟踪取决于给CascadeClassifier的特征库xml文件。


1.做特征库需要准备什么

在说这个之前,我要说的是制作特征库是一个很繁琐漫长的过程,训练过程从几秒到几周不等,而且即便是有耐心也未必能得到好的特征库,先做好心理准备吧。

首先,我们需要一套正样本和一套负样本图片。

什么叫做正样本和负样本?

正样本是你想跟踪的物体图像,各种角度,各种亮度,物体尽量占满整个图片,而且不要有太多背景,最好是纯色背景,并且大小相同。

而负样本是相反,你需要尽可能想象你在跟踪这个物体的时候,后面会有什么样的背景,把这些背景拍成照片,但是照片一定不能含有你需要跟踪的物体。

那么需要多少张呢?上篇用的人脸识别库据说正样本用了5000多张不同人种,不同肤色的人的正面照,而负样本用了7000多张。


2.准备好素材之后要还要准备什么?

成功编译安装opencv3.2.0之后,你的系统会有这两个可执行文件:opencv_createsamplesopencv_traincascade。

你需要创建一个用于生成特征库的目录sample,新建pos目录和neg目录,把你的正样本和负样本分别拷到pos和neg,创建pos.txt和neg.txt文件。

pos.txt记录了你所有正样本的信息,内容如下:


pos/0.png 1 0 0 200 200
pos/1.png 1 0 0 200 200
pos/10.png 1 0 0 200 200
pos/100.png 1 0 0 200 200
pos/101.png 1 0 0 200 200
pos/102.png 1 0 0 200 200
pos/103.png 1 0 0 200 200
pos/104.png 1 0 0 200 200
pos/105.png 1 0 0 200 200
pos/106.png 1 0 0 200 200
pos/107.png 1 0 0 200 200
pos/108.png 1 0 0 200 200
pos/109.png 1 0 0 200 200
pos/11.png 1 0 0 200 200
pos/110.png 1 0 0 200 200
pos/111.png 1 0 0 200 200
pos/112.png 1 0 0 200 200
pos/113.png 1 0 0 200 200
pos/114.png 1 0 0 200 200
pos/115.png 1 0 0 200 200
pos/116.png 1 0 0 200 200
pos/117.png 1 0 0 200 200
pos/118.png 1 0 0 200 200
pos/119.png 1 0 0 200 200
pos/12.png 1 0 0 200 200

...(你应该知道这个省略号的意思)


意思是:正样本图片文件相对位置  图片里面物体个数  物体位置x 物体位置y 物体宽度(pix) 物体高度(pix)


neg.txt记录的是负样本:

neg/0.png
neg/1.png
neg/10.png
neg/11.png
neg/12.png
neg/13.png
neg/14.png
neg/15.png
neg/16.png
neg/17.png
neg/18.png
neg/19.png
neg/2.png
neg/20.png

...(你应该知道这个省略号的意思)

它只需要负样本图片文件的相对位置就可以。


3.准备完毕后怎么做?

用终端进入sample,敲:

opencv_createsamples -info pos.txt -vec v.vec -bg neg.txt  -w 24 -h 24 -num x

x表示正样本的个数

这个命令完成后会生成v.vec文件

接下来新建training目录,敲:

opencv_traincascade -data training -vec v.vec -bg neg.txt -numPos x -numNeg y -numStages 20 -precalcValBufSize 5000 -precalcIdxBufSize 5000 -minHitRate 0.98 -maxFalseAlarmRate 0.5 -weightTrimRat 0.95 -w 24 -h 24

x先卖个关子,y表示负样本个数(可以大于实际个数)。

注意:-w 和 -h的参数一定要跟上个命令相同。

x之所以要卖关子,因为我怕你会做下面的事,然后发疯:

从字面上理解,numPos表示的是正样本个数。你大可以这么设置,但是,我敢保证你肯定会在漫长的等待后发现失败了。


那么x是什么意思呢?

先说一个公式:

pc >= (1 - hr)*(ns - 1)*np + np + [nc]

pc是正样本个数,hr是minHitRate,ns是numStages,np是numPos(也就是x),nc是负样本个数。

也就是说x必须满足这个公式才有可能成功。

那么为什么要在nc上加个[]呢?因为这个我也不确定nc表示负样本个数还是直接是0,有时候设0能成功,有时候直接失败。

接下来的事就是等,没错,等.....

你的cpu跟你的gpu会发疯,你的内存会被塞得毫无缝隙。没错,电脑用脑过度了。


4.有没有很快的方式来生成pos.txt和neg.txt呢?

笔者做了个小程序用来生成这两个文件,大体过程如下:

iOS开发之opencv学习笔记三:训练一套自己的特征库iOS开发之opencv学习笔记三:训练一套自己的特征库

iOS开发之opencv学习笔记三:训练一套自己的特征库

iOS开发之opencv学习笔记三:训练一套自己的特征库

最上面的按钮可以无视(不过你可以试一下)。

中间的按钮是让你选背景图片,并且到这些图片里面随机切图生成负样本到neg。

最后一个按钮是生成txt文件的,顺便自动生成命令文件shell.txt,不过上面说的numPos最好自己算一下。

什么???要积分???iOS开发之opencv学习笔记三:训练一套自己的特征库iOS开发之opencv学习笔记三:训练一套自己的特征库iOS开发之opencv学习笔记三:训练一套自己的特征库

码农不易,多多理解。