首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

浅析人脸检测之Haar分类器方法:Haar特征、积分图、 AdaBoost 、级联(2)

浅析人脸检测之Haar分类器方法:Haar特征、积分图、 AdaBoost 、级联(2)

2.2.2、弱分类器的孵化
        最初的弱分类器可能只是一个最基本的Haar-like特征,计算输入图像的Haar-like特征值,和最初的弱分类器的特征值比较,以此来判断输入图像是不是人脸,然而这个弱分类器太简陋了,可能并不比随机判断的效果好,对弱分类器的孵化就是训练弱分类器成为最优弱分类器,注意这里的最优不是指强分类器,只是一个误差相对稍低的弱分类器,训练弱分类器实际上是为分类器进行设置的过程。至于如何设置分类器,设置什么,我们首先分别看下弱分类器的数学结构和代码结构。
数学结构

       一个弱分类器由子窗口图像x,一个特征f,指示不等号方向的p和阈值Θ组成。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;

代码结构中的threshold即代表数学结构中的Θ阈值。
      这个阈值究竟是干什么的?我们先了解下CvCARTHaarClassifier这个结构,注意CART这个词,它是一种二叉决策树,它的提出者Leo Breiman等牛称其为“分类和回归树(CART)”。什么是决策树?我如果细讲起来又得另起一章,我只简略介绍它。
      “机器学习中,决策树是一个预测模型;他代表的是对象属性与对象值之间的一种映射关系。树中每个节点表示某个对象,而每个分叉路径则代表的某个可能的属性值,而每个叶结点则对应从根节点到该叶节点所经历的路径所表示的对象的值。决策树仅有单一输出,若欲有复数输出,可以建立独立的决策树以处理不同输出。从数据产生决策树的机器学习技术叫做决策树学习,通俗说就是决策树。”(来自《维基百科》)
决策树包含:分类树,回归树,分类和回归树(CART),CHAID。
分类和回归的区别是,
Ø  分类:是当预计结果可能为两种类型(例如男女,输赢等)使用的概念。
Ø  回归:是当局域结果可能为实数(例如房价,患者住院时间等)使用的概念。
       决策树用途很广可以分析因素对事件结果的影响(详见维基百科),同时也是很常用的分类方法,我举个最简单的决策树例子,假设我们使用三个Haar-like特征f1,f2,f3来判断输入数据是否为人脸,可以建立如下决策树:

        可以看出,在分类的应用中,每个非叶子节点都表示一种判断,每个路径代表一种判断的输出,每个叶子节点代表一种类别,并作为最终判断的结果。
        一个弱分类器就是一个基本和上图类似的决策树,最基本的弱分类器只包含一个Haar-like特征,也就是它的决策树只有一层,被称为树桩(stump)。
        最重要的就是如何决定每个结点判断的输出,要比较输入图片的特征值和弱分类器中特征,一定需要一个阈值,当输入图片的特征值大于该阈值时才判定其为人脸。训练最优弱分类器的过程实际上就是在寻找合适的分类器阈值,使该分类器对所有样本的判读误差最低。
具体操作过程如下:
1)对于每个特征 f,计算所有训练样本的特征值,并将其排序。
扫描一遍排好序的特征值,对排好序的表中的每个元素,计算下面四个值:
全部人脸样本的权重的和t1;
全部非人脸样本的权重的和t0;
在此元素之前的人脸样本的权重的和s1;
在此元素之前的非人脸样本的权重的和s0;
2)最终求得每个元素的分类误差
        在表中寻找r值最小的元素,则该元素作为最优阈值。有了该阈值,我们的第一个最优弱分类器就诞生了。
在这漫长的煎熬中,我们见证了一个弱分类器孵化成长的过程,并回答了如何得到弱分类器以及二叉决策树是什么。最后的问题是强分类器是如何得到的。


2.2.3、弱分类器的化蝶飞
首先看一下强分类器的代码结构:
/* 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个样本,其中X和Y分别对应于正样本和负样本; T为训练的最大循环次数;  
2. 初始化样本权重为1/N,即为训练样本的初始概率分布;  
3. 第一次迭代训练N个样本,得到第一个最优弱分类器,步骤见2.2.2节
4. 提高上一轮中被误判的样本的权重;
5. 将新的样本和上次本分错的样本放在一起进行新一轮的训练。
6. 循环执行4-5步骤,T轮后得到T个最优弱分类器。
7.组合T个最优弱分类器得到强分类器,组合方式如下:
          

相当于让所有弱分类器投票,再对投票结果按照弱分类器的错误率加权求和,将投票加权求和的结果与平均投票结果比较得出最终的结果。
      至此,我们看到其实我的题目起的漂亮却并不贴切,强分类器的脱颖而出更像是民主的投票制度,众人拾材火焰高,强分类器不是个人英雄主义的的产物,而是团结的力量。但从宏观的局外的角度看,整个AdaBoost算法就是一个弱分类器从孵化到化蝶的过程。小人物的奋斗永远是理想主义者们津津乐道的话题。但暂时让我们放下AdaBoost继续探讨Haar分类器的其他特性吧。
继承事业,薪火相传
返回列表