在opencv源代码中如何确定树桩分类器阈值?如何确定树桩的左右边的返回值?

原创 2015年07月08日 16:56:58

源代码在opencv库里面的cvboost.cpp文件里面,宏ICV_DEF_FIND_STUMP_THRESHOLD( suffix, type, error )的总体思路是通过定义带参数的宏,把参数传递给宏内部的函数,然后进行一系列的计算,并最终根据一定的算法找到合适的阈值。具体解析如下:

#define ICV_DEF_FIND_STUMP_THRESHOLD( suffix, type, error )                              \
static int icvFindStumpThreshold_##suffix(                                               \
        uchar* data, size_t datastep, //训练样本的  特征-样本数据                        \
        uchar* wdata, size_t wstep, //wdata是样本的权重矩阵                               \
        uchar* ydata, size_t ystep, //ydata是样本的类别矩阵                               \
        uchar* idxdata, size_t idxstep, int num, //idxdata是样本根据特征值大小排序后的索引数据,样本按照特征值的大小升序排列  \
        float* lerror, //左边不纯度                                                       \
        float* rerror, //右边不纯度                                                       \
        float* threshold, float* left, float* right,                                     \
        float* sumw, float* sumwy, float* sumwyy )                                       \
{                                                                                        \
    int found = 0;                                                                       \
    float wyl  = 0.0F;                                                                   \
    float wl   = 0.0F;                                                                   \
    float wyyl = 0.0F;                                                                   \
    float wyr  = 0.0F;                                                                   \
    float wr   = 0.0F;                                                                   \
                                                                                         \
    float curleft  = 0.0F;                                                               \
    float curright = 0.0F;                                                               \
    float* prevval = NULL;                                                               \
    float* curval  = NULL;                                                               \
    float curlerror = 0.0F;                                                              \
    float currerror = 0.0F;                                                              \
                                                                                         \
    int i = 0;                                                                           \
    int idx = 0;                                                                         \
                                                                                         \
    if( *sumw == FLT_MAX )                                                               \
    {                                                                                    \
        /* calculate sums */                                                             \
        float *y = NULL;                                                                 \
        float *w = NULL;                                                                 \
        float wy = 0.0F;                                                                 \
                                                                                         \
        *sumw   = 0.0F;                                                                  \
        *sumwy  = 0.0F;                                                                  \
        *sumwyy = 0.0F;                                                                  \
        for( i = 0; i < num; i++ )                                                       \
        {                                                                                \
            idx = (int) ( *((type*) (idxdata + i*idxstep)) );//根据样本的数据和step确定其样本索引序号idx  \
            w = (float*) (wdata + idx * wstep);                                          \
            *sumw += *w;                        //计算权重和                              \
            y = (float*) (ydata + idx * ystep);                                          \
            wy = (*w) * (*y);                   //计算权重w和类别y的乘积                  \
            *sumwy += wy;                                                                \
            *sumwyy += wy * (*y);                                                        \
        }                                                                                \
    }                                                                                    \
                                                                                         \
    for( i = 0; i < num; i++ )                                                           \
    {                                                                                    \
        idx = (int) ( *((type*) (idxdata + i*idxstep)) );                                \
        curval = (float*) (data + idx * datastep);                                       \
         /* for debug purpose */                                                         \
        if( i > 0 ) assert( (*prevval) <= (*curval) );                                   \
                                                                                         \
        wyr  = *sumwy - wyl;//计算在当前特征值以前的去除重复的特征值后的权重和类别乘积和\
        wr   = *sumw  - wl;  //计算在当前特征值以前的去除重复的特征值后的权重和          \
                                                                                         \
        if( wl > 0.0 ) curleft = wyl / wl;    //在剔除出有相同特征值的样本中,计算正样本比重(因为负样本的类别为0)\
        else curleft = 0.0F;                                                             \
                                                                                         \
        if( wr > 0.0 ) curright = wyr / wr;   //在未剔除出的样本中,计算正样本的权重和比重 \
        else curright = 0.0F;                                                            \
                                                                                         \
        error                                                                            \
                                                                                         \
        if( curlerror + currerror < (*lerror) + (*rerror) )//如果当前的不纯度和小于原来的不纯度和\
        {                                                                                \
            (*lerror) = curlerror;                                                       \
            (*rerror) = currerror;                                                       \
            *threshold = *curval;                                                        \
            if( i > 0 ) {   
/************************树桩分类器的阈值:0.5*(当前特征值值与前一个特征值的和)*************************/               
                *threshold = 0.5F * (*threshold + *prevval); //阈值的大小为0.5*(当前特征值值与前一个特征值的和)  \
            }                                                                            \
            *left  = curleft;//树桩分类器的左边的返回值                                   \
            *right = curright;//树桩分类器右边的返回值                                    \
            found = 1;                                                                   \
        }                                                                                \
                                                                                         \
        do                                                                               \
        {   //在计算参数时,也就是计算与当前特征值重复的特征值的相关参数                 \
            wl  += *((float*) (wdata + idx * wstep));                                    \
            wyl += (*((float*) (wdata + idx * wstep)))                                   \
                * (*((float*) (ydata + idx * ystep)));                                   \
            wyyl += *((float*) (wdata + idx * wstep))                                    \
                * (*((float*) (ydata + idx * ystep)))                                    \
                * (*((float*) (ydata + idx * ystep)));                                   \
        }                                                                                \
        while( (++i) < num &&                                                            \
            ( *((float*) (data + (idx =                                                  \
                (int) ( *((type*) (idxdata + i*idxstep))) ) * datastep))                 \
                == *curval ) );
   /*
    *do-while作用:计算与当前重复特征值的wl,wyl,wyyl。
    *while括号里的含义是当i<num时,并且idxdata中的第++i个特征值与当前的特征值相等时,就执行
    *do-while循环里的内容。对于同一个特征值,如果做阈值的话,对于分类结果只能是同一种情况
    *,所以要跳过对同一个相等的特征值来确定阈值的情况,另一个作用是这样也无形中加快了训练
    *过程。
    */
                                                                                         \
        --i;                                                                             \
        prevval = curval;  //把当前特征值变成前一个,依次遍历所有的特征值,并最终选择一个最优的阈值 \
    } /* for each value */                                                               \
                                                                                         \
    return found;                                                                        \
} 


相关文章推荐

在opencv中,强分类器阈值是如何确定的?虚警率是怎么计算的?

在opencv中,强分类器阈值的确定实在函数icvCreateCARTStageClassifier中,具体强分类器的阈值的求解方式和虚警率的计算如下 CvIntHaarClassifier* icv...

Fisher线性分类器(2)--- 各最优参数的确定

1、说明       前面已提到,在非参数判别分类方法中,首先必须确定准则函数(假设样本是线性可分的),然后根据样本集求出使得准则函数达到极值的分类器参数,对于线性分类器,其典型形式为:,因此需要确定...

OpenCV生成XML分类器文件

  • 2013年08月21日 17:54
  • 4.46MB
  • 下载

OpenCV - 训练分类器

  • 2016年10月22日 10:33
  • 39.78MB
  • 下载

icvCreateCARTStageClassifier训练强分类器源代码框架

icvCreateCARTStageClassifier函数的详细分析见我博文中的另外一篇文章http://blog.csdn.net/ding977921830/article/details/46...

opencv之利用harr分类器人脸检测

  • 2016年01月30日 17:03
  • 4.45MB
  • 下载

opencv 基于haar特征车牌分类器

  • 2017年05月30日 18:36
  • 52KB
  • 下载

opencv K邻近分类器的使用

利用Mat数据类型训练Opencv K邻近分类器,下面是手册中给出的K邻近分类器使用的例子,该例子是以CvMat形式实现的。通过下面的例子可以知道如何使用Opencv自带的分类器、矩阵数据如何访问、如...
  • kxuehen
  • kxuehen
  • 2014年12月17日 19:14
  • 692
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在opencv源代码中如何确定树桩分类器阈值?如何确定树桩的左右边的返回值?
举报原因:
原因补充:

(最多只允许输入30个字)