代码改变世界

Adaboost算法

2014-02-24 13:00  valerlina  阅读(781)  评论(0编辑  收藏  举报

 

Haar分类器算法:

(1)使用Haar-like特征做检测;

(2)使用积分图(Intergral Image)对Haar-like特征求值进行加速。

(3)使用Adaboost算法训练区分人脸和非人脸的强分类器。

(4)使用筛选式级联把强分类器级联到一起,提高准确率。

 

1Haar-like特征:

特征:假设在人脸检测时我们需要有这么一个子窗口在待检测的图片窗口中不断的移位滑动,子窗口每到一个位置,就会计算出该区域的特征,然后用我们训练好的级联分类器对该特征进行筛选,一旦该特征通过了所有强分类器的筛选,则判定该区域为人脸。

Haar-like特征:

 

图1 Viola提出的Haar-like特征:原始的矩阵特征

将上面的任意一个矩形放到人脸区域上,然后,将白色区域的像素和减去黑色区域的像素和,得到的值我们暂且称之为人脸特征值,如果你把这个矩形放到一个非人脸区域,那么计算出的特征值应该和人脸特征值是不一样的,而且越不一样越好,所以这些方块的目的就是把人脸特征量化,以区分人脸和非人脸。

(2)积分图(Intergral Image

积分图是一种能够描述全局信息的矩阵表示方法。积分图的构造方式是位置(x,y)处的值ii(x,y)是原图像(x,y)左上角方向所有像素的和: 

 

积分图构建算法: 

1)用s(x,y)表示行方向的累加和;

2)用ii(x,y)表示一个积分图像; 

3)逐行扫描图像,递归计算每个像素(x,y)行方向的累加和s(x,y)和积分图像ii(x,y)的值:

s(x,y)=s(x,y-1)+i(x,y)

ii(x,y)=ii(x-1,y)+s(x,y)

4)扫描图像一遍,当到达图像右下角像素时,积分图像ii就构造好了。

积分图构造好之后,图像中任何矩阵区域的像素累加和都可以通过简单运算得到如图所示。

 

区域D的像素累加和应为:4-2-3+1

由于Haar-like特征值是两个矩阵像素和的差,因此可以可用积分图很快的计算出此特征值。

3Adaboost算法

Adaboost算法用来选出矩形特征组合,并且确定怎样将这些特征组合以用来更好的区分出人脸和非人脸。

这里提到的矩阵特征组合就是分类器,分类器将矩阵组合以二叉决策树的形式存储起来。

弱学习:就是指一个学习算法对一组概念的识别率只比随机识别好一点; 

强学习:就是指一个学习算法对一组概率的识别率很高。

弱分类器和强分类器就是弱学习算法和强学习算法。弱学习算法是比较容易获得的,获得过程需要数量巨大的假设集合,这个假设集合是基于某些简单规则的组合和对样本集的性能评估而生成的,而强学习算法是不容易获得的,然而,只要有足够的数据,弱学习算法就能通过集成的方式生成任意高精度的强学习方法。

弱分类器:

最初的弱分类器可能只是一个最基本的Haar-like特征,计算输入图像的Haar-like特征值,和最初的弱分类器的特征值比较,以此来判断输入图像是不是人脸,然而这个弱分类器太简陋了,可能并不比随机判断的效果好,对弱分类器的孵化就是训练弱分类器成为最优弱分类器,训练弱分类器实际上是为分类器进行设置的过程。

弱分类器的数学结构和代码结构:

 

其中,h(x,f,p,)是基于简单特征的分类器,x是待检测子窗口,f(x)是对于子窗口x的矩形特征值计算函数,p是符号因子(对于不同的特征,计算得到的特征值中有可能负样本的值小于正样本,也有可能负样本的值大于正样本,因此,正样本不都是小于区分正负样本的阈值的,也有可能大于,所以引入一个符号因子来确定不等式的方向),为对应分类器的阈值。对于每个特征f,训练一个弱分类器h(x,f,p,),就是确定f的最优阈值,使得这个弱分类器h(x,f,p,)对所有的训练样本的分类误差最低。

/*

 * CART classifier

 */

typedef struct CvCARTHaarClassifier

{

    CV_INT_HAAR_CLASSIFIER_FIELDS()

 

    int count;

    int* compidx;

    CvTHaarFeature* feature;

    CvFastHaarFeature* fastfeature;

    float* threshold;   //代表公式中的阈值

    int* left;

    int* right;

    float* val;

} CvCARTHaarClassifier;

CART分类和回归树:二叉决策树:

分类:是当预计结果可能为两种类型(例如男女,输赢等)使用的概念。

回归:是当局域结果可能为实数(例如房价,患者住院时间等)使用的概念。

举个最简单的决策树例子,假设我们使用三个Haar-like特征f1f2f3来判断输入数据是否为人脸,可以建立如下决策树:

 

可以看出,在分类的应用中,每个非叶子节点都表示一种判断,每个路径代表一种判断的输出,每个叶子节点代表一种类别,并作为最终判断的结果。

一个弱分类器就是一个基本和上图类似的决策树,最基本的弱分类器只包含一个Haar-like特征,也就是它的决策树只有一层,被称为树桩(stump)。

最重要的就是如何决定每个结点判断的输出,要比较输入图片的特征值和弱分类器中特征,一定需要一个阈值,当输入图片的特征值大于该阈值时才判定其为人脸。

训练最优弱分类器的过程实际上就是在寻找合适的分类器阈值,使该分类器对所有样本的判读误差最低。

弱分类器训练具体操作过程如下: 

1)对于每个特征f,计算所有训练样本的特征值

2)将特征值排序;

3)对排好序的每个元素:计算下面四个值: 

全部人脸样本(即正样本)的权重的和T+; 

全部非人脸样本(即负样本)的权重的和T-; 

在此元素之前的人脸样本的权重的和S+; 

在此元素之前的非人脸样本的权重的和S-; 

4)选取当前元素的特征值,和它前面的一个特征值之间的数作为阈值,该阈值的分类误差为:

 

这样,当选取当前元素的特征值和它前面的一个特征时之间的数作为阈值时,所得到的弱分类器就在当前元素处把样本分开——也就是说这个阈值对应的弱分类器将当前元素前的所有元素分类为人脸(或非人脸),而把当前元素后(含)的所有元素分类为非人脸(或人脸)。

于是,通过把已排序的表从头到尾扫描一遍就可以为弱分类器选择使分类误

差最小的阈值(最优阈值),也就是选取了一个最佳的弱分类器。

强分类器:

/* internal stage classifier */

typedef struct CvStageHaarClassifier

{

    CV_INT_HAAR_CLASSIFIER_FIELDS()

 

    int count;

    float threshold;

    CvIntHaarClassifier** classifier;

} CvStageHaarClassifier;

/* internal weak classifier*/

typedef struct CvIntHaarClassifier

{

    CV_INT_HAAR_CLASSIFIER_FIELDS()

} CvIntHaarClassifier;

CvIntHaarClassifier结构:它就相当于一个接口类,当然是用C语言模拟的面向对象思想,利用CV_INT_HAAR_CLASSIFIER_FIELDS()这个宏让弱分类器CvCARTHaarClassifier和强分类器CvStageHaarClassifier继承于CvIntHaarClassifier

强分类器的诞生需要T轮的迭代,具体操作如下: 

1. 给定训练样本集S,共N个样本,其中XY分别对应于正样本即人脸样本和负样本即非人脸样本; T为训练的最大循环次数; 

2. 初始化样本权重为1/N,即为训练样本的初始概率分布; 

3. 第一次迭代训练N个样本,得到第一个最优弱分类器,参见上面的讨论

4. 提高上一轮中被误判的样本的权重; 

5. 将新的样本和上次本分错的样本放在一起进行新一轮的训练。

6. 循环执行4-5步骤,T轮后得到T个最优弱分类器。

7. 组合T个最优弱分类器得到强分类器,组合方式如下: