在opencv源代码中如何确定树桩分类器阈值?如何确定树桩的左右边的返回值?
2015-07-08 16:56
351 查看
源代码在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; \ }
相关文章推荐
- python初学-03控制流程
- php+mysql 解决emoji问题
- Java中的值传递和引用传递
- 在asp.net 中应用POST传递和接收XML文件以及参数.(转)
- S标签库
- Java小Tips
- java Date获取 年月日时分秒
- 总结Django中的用户权限模块
- SecureCRT vbs脚本小记
- 面向对象编程的特征以及常用的修饰符
- C++的XML编程经验――LIBXML2库使用指南
- 安装MySQL后无法打开wamp中的phpadmin的解决办法
- java集合框架
- Spring事务配置的五种方式
- 怎样管理C++类中的指针成员 和 简单的c++智能指针使用的例子
- java 不用科学计数法显示Double类型和Long类型
- 【Java】实现一个算法,找出一个单链表中倒数第K个结点
- java 开发微型公众账号应用
- C++ Primer学习笔记(13)——封装、继承、多态
- Eclipse中的全局搜索