在(3)中把opencv_traincascade在使用LBP特征的时候的训练准备工作的代码总结了下。下面开始硬着头皮看训练里面的部分了。介于这部分实在是没怎么找到网上介绍的帖子(为啥呢???)所以总结的大部分内容是自己猜测的。以后再回头慢慢完善。
接着上次结束的部分,训练一个强分类器的代码是:
bool CvCascadeBoost::train( const CvFeatureEvaluator* _featureEvaluator,//包含了sum,tilted,特征的位置等信息
int _numSamples,
int _precalcValBufSize, int _precalcIdxBufSize,
const CvCascadeBoostParams& _params )
{
CV_Assert( !data );
clear();
data = new CvCascadeBoostTrainData( _featureEvaluator, _numSamples,
_precalcValBufSize, _precalcIdxBufSize, _params );//目前暂且知道这里是调用preCalculate计算所有的特征值
CvMemStorage *storage = cvCreateMemStorage();
weak = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvBoostTree*), storage );
storage = 0;
set_params( _params );
if ( (_params.boost_type == LOGIT) || (_params.boost_type == GENTLE) )
data->do_responses_copy();
update_weights( 0 );
cout << "+----+---------+---------+" << endl;
cout << "| N | HR | FA |" << endl;
cout << "+----+---------+---------+" << endl;
do
{
CvCascadeBoostTree* tree = new CvCascadeBoostTree;
if( !tree->train( data, subsample_mask, this ) )//应该是训练一个弱分类器tree
{
delete tree;
break;
}
cvSeqPush( weak, &tree );//把弱分类器添加到强分类器里面
update_weights( tree );//AdaBoost里面更新weight部分。
trim_weights();
if( cvCountNonZero(subsample_mask) == 0 )
break;
}
while( !isErrDesired() && (weak->total < params.weak_count) );
data->is_classifier = true;
data->free_train_data();
return true;
}
这里面主要分为
调用preCalculate计算所有样本的所有的特征值
训练一个弱分类器
根据AdaBoost里面的步骤把样本的weight都更新一遍
主要看如何训练一个弱分类器。因为在(4)中总结output的xml文件结构的时候发现每一个node里面都包含了8个很大的数,后来在predict函数里看到这8个数是属于subset,在使用xml文件的时候用里面每一个feature算出来的特征值转换为二进制后是256个bit,然后跟这8个大数的最后32个位进行比较,如果有至少一个bit都是1的话那么就输出一个值,反之另一个值。在这需要指出的是,如果是haar-like feature的话用的不是subset而是threshold,后面比较后就一样了。而且haar-like基本上是一个feature一个弱分类器,而这里subset里可以有多个1出现,所以我理解着就是指有多个feature组成的subset。
而这些subset是如何求出来的呢,我跟踪程序总结如下。(里面用到好多opencv里面ml的数据结构,到现在感觉还是没有入门啊)
boost.cpp里:
bool
CvBoostTree::train( CvDTreeTrainData* _train_data,
const CvMat* _subsample_idx, CvBoost* _ensemble )
{
clear();
ensemble = _ensemble;
data = _train_data;
data->shared = true;
return do_train( _subsample_idx );//去CvDTree里训练弱分类器去
}
然后在tree.cpp里
bool CvDTree::do_train( const CvMat* _sub