OpenCV 人脸检测自学(2)

在看了文档[2,3]后开始对照着看OpenCV代码,看得晕头转向啊。又搜了网上的一些帖子,先针对自己的理解做笔记如下,日后好在此基础上补充。

OpenCV人脸检测之数据结构:

所有的结构都代表一个级联boosted Haar分类器。级联有下面的等级结构:

Cascade:

Stage1:

Classifier11:

Feature11

Classifier12:

Feature12

...

Stage2:

Classifier21:

Feature21

...

...

关于特征

OpenCV 人脸检测自学(2)_第1张图片

typedef struct CvTHaarFeature//Haar-like 特征

{

    char desc[CV_HAAR_FEATURE_DESC_MAX];// haar_x3等描述feature的形状

    int  tilted;//0->up-rightfeature, 1->45 rotated feature 见上图。

    struct

    {

        CvRect r;

        float weight;

    } rect[CV_HAAR_FEATURE_MAX];//一个feature由2-3个长方形组成

CvTHaarFeature;

 

typedef struct CvFastHaarFeature

{

    int tilted; //0->up-right feature, 1->45rotated feature 见上图。

    struct

    {

        int p0p1p2p3;//把上面的Feature中的r的四个角点位置按照图像左上角开始算起第几个(offset)。这样方便后面等积分图算出来后直接把p0,p1,p2,p3当做下标来取积分数值即可。

        float weight;

    } rect[CV_HAAR_FEATURE_MAX];

CvFastHaarFeature;

 

typedef struct CvIntHaarFeatures

{

    CvSize winsize;

    int count;

    CvTHaarFeaturefeature;

    CvFastHaarFeaturefastfeature;

CvIntHaarFeatures;

 

/* Prepared for training samples */

typedef struct CvHaarTrainingData

{

    CvSize winsize;    /* training image size */

    int    maxnum;      /* maximumnumber of samples *///(2000+2000)

    CvMat  sum;         /* sumimages (each row represents image) *///(2000+2000) x (20x20)

    CvMat  tilted;      /* tilted sumimages (each row represents image) *///(2000+2000) x (20x20)

    CvMat  normfactor;  /* normalizationfactor */

    CvMat  cls;         /* classes.1.0 - object, 0.0 - background */// 1 x (2000+2000)

    CvMat  weights;     /* weights *///1 x (2000+2000)Adaboost训练的时候需要的样本权值

    CvMatvalcache;   /* precalculated feature values (CV_32FC1) */

    CvMatidxcache;   /* presorted indices (CV_IDX_MAT_TYPE) */

CvHaarTrainigData;

 

typedef struct CvUserdata

{

    CvHaarTrainingDatatrainingData;

    CvIntHaarFeatureshaarFeatures;

CvUserdata;

以上描述的结构体可总结如下[1].

OpenCV 人脸检测自学(2)_第2张图片

关于分类器

typedef struct CvCARTHaarClassifier//基于Haar-like特征的弱分类器

{

    CV_INT_HAAR_CLASSIFIER_FIELDS()

 

    int count;//这个弱分类器需要的Haar-like特征数目,如果上传调用时nsplits为1这个count值即为1,也就是说一般理解的弱分类器。

    intcompidx;//选择出的这个弱分类器的Haar-like特征的序号

    CvTHaarFeaturefeature; //选择出的这个弱分类器的Haar-like特征

    CvFastHaarFeaturefastfeature; //选择出的这个弱分类器的Haar-like特征

    floatthreshold; //选择出的这个弱分类器的Haar-like特征的threshold

    intleft;//跟CART树有关,应该是Node的序号

    intright; //跟CART树有关,应该是Node的序号

    floatval;//跟上面的threshold比较后的output值,其实是code里面的Curleft和curright

CvCARTHaarClassifier;

 

typedef struct CvStageHaarClassifier//基于Haar-like特征的强分类器

{

    CV_INT_HAAR_CLASSIFIER_FIELDS()

    int count;

    float threshold;//强分类器的threshold,大于此值的output为1,小于此值的output为0

    CvIntHaarClassifier** classifier;//被转化为弱分类器CvCARTHaarClassifier,

CvStageHaarClassifier;

 

typedef struct CvCascadeHaarClassifier//基于Haar-like特征的级联强分类器

{

    CV_INT_HAAR_CLASSIFIER_FIELDS()

    int count;

   CvIntHaarClassifier** classifier; //被转化为强分类器CvStageHaarClassifier

CvCascadeHaarClassifier;

 

/* internal weak classifier*/

typedef struct CvIntHaarClassifier

{//感觉像是c++里的抽象类的意思

    CV_INT_HAAR_CLASSIFIER_FIELDS()

CvIntHaarClassifier;

 

那么这里为什么要使用一个如此复杂的结构呢。大体来说有两个好处:
1
、 方便弱分类器之间的切换,当我们不选用CART而是其他的弱分类器结构的时候,就可以调用CvIntHaarClassifier时转换成其他的指针
2
、 这样方便了Haar训练的过程和Boost过程的衔接。

训练部分的接口及流程图

OpenCV 有cvCreateTreeCascadeClassifier和cvCreateCascadeClassifier两种级联分类器,目前先讨论后者。

创建Cascade分类器:

void cvCreateCascadeClassifier(

const chardirname,//工作目录

const charvecfilename,//正样本的描述文件,其中包含正样本的数目,宽高,以及所有样本图像数据

const charbgfilename,//负样本的描述文件,只包含负样本的路径

int npos, //用于训练的正样本的数目

int nneg, //用于训练的负样本的数目

int nstages,//训练多少层

int numprecalculated, //MB

int numsplits, //在一个弱分类器中用的feature数目,1->stump classifier; 2或更多 -> CARTclassifier

float minhitrate, //每一个stage在训练的时候需要达到的最低hit rate

float maxfalsealarm,//每一个stage在训练的时候允许达到的最高的false alarm rate

float weightfraction,//boosting算法的一个参数

int mode, //BASIC-> only uprightfeatures; ALL->full set of upright and 45度features;

int symmetric,//对称的话可以加快训练进程

int equalweights,//enable equal weightsfor positives and negatives.

int winwidth, //width of training images

int winheight, //height of training images

int boosttype, //DAB->Discrete Ada Boost;RAB->Real Ada Boost; LB->Logic Boost; GAB->Gentle Adaboost

int stumperror,//跟DAB有关的一个参数

)

 OpenCV 人脸检测自学(2)_第3张图片 

创建Gentle Adaboost强分类器:

OpenCV 人脸检测自学(2)_第4张图片

OpenCV 人脸检测自学(2)_第5张图片

创建弱分类器:(以stump为例)
下图不是我做的,是[1]里的,openCV里的代码顺序跟这个稍有出入,但是基本一致。

 OpenCV 人脸检测自学(2)_第6张图片

Curleft和curright 即为跟threshold比较后的output

  

Reference

1. http://wenku.baidu.com/view/87fccf09581b6bd97f19ea12.html

2. "Empirical Analysis of Detection Cascades of Boosted Classifiers for Rapid Object Detection" , Rainer Lienhart, Alexander Kuranov, Vadim Pisarevsky,2002

3. “Rapid Object Detection using a Boosted Cascade of Simple Features”, Paul Viola, Michael Jones, 2001

 

你可能感兴趣的:(OpenCV 人脸检测自学(2))