这里说说我对这个算法的理解:

主要应用在人脸检测。haar特征 + adaboosting,人脸检测系统是一个级联的分类器系统,这里主要是讨论其中一个节点。

大体流程如果:

 

                

首先准备正负样本,在一个训练强分类器H时,使用booststraping策略来进行样本的提取:从整体样本集合中,抽样n1 < n个样本 针对抽样的集合训练分类器H1,,抽样的方法有很多,例不放回抽样等.当训练第二强分类器时,从样本整体集合D中,抽取 nn 个样本,其中合并进一半被 C1 分类错误的样本。得到样本集合 D2,训练弱分类器H2,抽取D样本集合中,H1 和 H2 分类不一致样本,组成D3,训练弱分类器H3

特征的选择:20 * 20 的图像

这里的尺度需要缩放,使得目标的大小具有更大适应性,根据给定的参数,特征的数量大概是67067(主要是为了能加速训练的过程,所以增加了一些限制)。在训练前对图像进行直方图均衡化(光照补偿)。

具体的haar特征提取参考:http://www.cnblogs.com/ello/archive/2012/04/28/2475419.html

系统使用haar特征的原因在于它的简单,计算复杂度低,可以达到实时性的目的。

Adaboost(Adaptive Boosting)算法 是一个将几个弱分类器结合起来,说白了就是几个臭皮匠顶个诸葛亮,不过不同于boostraping,它不是紧紧将几个弱分器的相加,而是需要样本权值来使得每次弱分类器的连续,涉及到权值的选择和更新,在抵抗噪声干扰使用的是权值修正 (Weight trimming)。如果分类正确了,权重降低,如果分类错了,则权重提高,初始的时候,权重都是一样的。通过多次迭代,可以想象得到,程序越往后执行,训练出的模型就越会在意那些容易分错(权重高)的点。当全部的程序执行完后,会得到M个模型在整个训练过程中其实就是一个贪婪算法,在每一次训练弱分类器的时候,都需要对所有的特征进行一个迭代,选择一个能是使得目标误差函数最小的特征作为弱分类器的特征(相当每个特征对应一个弱分类器),所以adaboosting算法也被认为是一个特征选择算法。算法之所以称为自适应,因为在每次迭代过程中会根据分类的结果来调整权值,这里也就是adaboost与boosting算法的最大差异。

adaboost/boosting 的差异:http://www.cnblogs.com/fartherfuture/p/3678668.html

adaboosting算法的流程如下:

整个过程完成之后,就得到一个强分类器。 之后通过样本选择策略来更新样本,再训练得到一个强分类器。。。。。

通过多个分类器结合起来得到一个级联分类器(强强联合)。

在Opencv2.4.8里有具体的函数或者应用程序来选择样本和训练级联分类器。

 

CreateSample 使用的是Opencv_createSample.exe 应用程序,具体参见文档:Opencv 之 HaarTraining算法剖析 作者周明才,讲的很好

下面是我根据文档的结果

Opencv_haartrainging d的参数中最值得注意的就是 -npos 和 -nneg ,参数-nstages 表示级联分类器的级数nstages, -minhitrate 表示最小命中率,默认是0.95

-npos 代表的是正样本的数目,是指在训练一个强分类器从.vec文件中抽样出来的数据样本,-nneg表示训练一个强分类器的负样本数目。

假设.vec文件的数目是CountVec,那么有这样一个不等式成立

CountVec >= (npos + (nstages - 1)*(1 -minhitrate) * npos ) + nneg 

为什么需要满足这个不等式呢?

主要原因在于每一个强分类器时样本的选择上,在 stage=0时,随机的从.vec文件中选择npos个正样本,由于存在虚警,在每一次训练一个强分类器之后,会把那些分类错误的从整个样本库中剔除掉,总的样本就剩下 CountVec = CountVec - (1 - minhitrate)* npos,在第二个强分类器的训练过程中就是从剩下的Countvec抽样,一直这样进行nstage次,所以就有CountVec >= (npos + (nstages - 1)*(1 -minhitrate) * npos ) + nneg 。

当在使用opencv_haartraining 训练的时候,出现如下的报错

Opencv Error:Assert failed (elements_read == 1) in icvGetHaarTraininDataFrom

那么基本可以认定Countvec的个数不足于一次强分类器的训练也就是这个时候 Countvec < npos.