OpenCV的softcascade代码解读

//头文件为softcascade.hpp、core.hpp
//实现文件为octave.cpp
//但是还涉及到了ml.hpp和Dtree.cpp等文件
//softcascade检测器训练函数的代码如下:

bool BoostedSoftCascadeOctave::train(const Dataset* dataset, const FeaturePool* pool, int weaks, int treeDepth)
{//第1个参数dataset是一个可以与训练集通信的实例,第2个参数表示特征集,第3个参数是需要训练的弱分类器树数量,第4个参数是分类器树的深度
    CV_Assert(treeDepth == 2); //?要求弱分类树的深度只能为2吗?
    CV_Assert(weaks > 0);

params.max_depth  = treeDepth;
    params.weak_count = weaks;

// 1. fill integrals and classes,?这里计算了每个样本的所有积分图和标定了标签吗?是的,对于正样本,response向量中响应的元素值设置为了1,负样本设置为了0
    processPositives(dataset);
    generateNegatives(dataset);

// 2. only simple case (all features used) //使用所有的特征
    int nfeatures = pool->size();
    cv::Mat varIdx(1, nfeatures, CV_32SC1);
    int* ptr = varIdx.ptr<int>(0);

for (int x = 0; x < nfeatures; ++x)
        ptr[x] = x;

// 3. only simple case (all samples used) //使用所有训练样本
    int nsamples = npositives + nnegatives;
    cv::Mat sampleIdx(1, nsamples, CV_32SC1);
    ptr = sampleIdx.ptr<int>(0);

for (int x = 0; x < nsamples; ++x)
        ptr[x] = x;

// 4. ICF has an ordered response.
    cv::Mat varType(1, nfeatures + 1, CV_8UC1); //指定按特征响应排序?最后多的一个元素表示什么意思?是不是表示将要输入训练函数train()(在倒数第3行)中的response向量保存的是类标签
    uchar* uptr = varType.ptr<uchar>(0);
    for (int x = 0; x < nfeatures; ++x)
        uptr[x] = CV_VAR_ORDERED; //这个排序无法理解!
    uptr[nfeatures] = CV_VAR_CATEGORICAL;

trainData.create(nfeatures, nsamples, CV_32FC1); //生成用来训练用的数据矩阵,看下面的双重循环就知道,其中每行对应到一个特征,每列对应到一个样本,该矩阵每个元素保存的是某样本某特征的积分图。

for (int fi = 0; fi < nfeatures; ++fi)
    {
        float* dptr = trainData.ptr<float>(fi);
        for (int si = 0; si < nsamples; ++si)
        {
            dptr[si] = pool->apply(fi, si, integrals);
        }
    }

cv::Mat missingMask;

bool ok = train(trainData, responses, varIdx, sampleIdx, varType, missingMask); //?主要的训练函数,trainData是用特征表示的训练集矩阵,responses是样本对应的类标签,varIdx是所学习的特征的所有索引,sampleIdx是训练样本的索引,?varType表示是否对特征响应排序?,missingMask用来保存错误的分类。
    if (!ok)
        CV_Error(CV_StsInternal, "ERROR: tree can not be trained");
    return ok;

}

//其中用到的训练函数如下,可见它调用了boost类的train()函数,并且推测得到的检测器保存在params中。
//它调用了CvBoostTree::train()函数来,并加入了params参数,看来在BoostedSoftCascadeOctave类中没有params成员,但是最终的检测器时保存在该成员中的,到现在为止还是训练整个的检测器:
bool BoostedSoftCascadeOctave::train( const cv::Mat& _trainData, const cv::Mat& _responses, const cv::Mat& varIdx,
      const cv::Mat& sampleIdx, const cv::Mat& varType, const cv::Mat& missingDataMask)
{
    bool update = false;
    return cv::Boost::train(_trainData, CV_COL_SAMPLE, _responses, varIdx, sampleIdx, varType, missingDataMask, params,
    update);
}

//boost类的train()函数定义如下(在boost.cpp中):
bool
CvBoost::train( const CvMat* _train_data, int _tflag,
              const CvMat* _responses, const CvMat* _var_idx,
              const CvMat* _sample_idx, const CvMat* _var_type,
              const CvMat* _missing_mask,
              CvBoostParams _params, bool _update )
{//顺着来,到了这里,_train_data是训练数据,每行对应到一个特征每列对应到一个样本;_tflag表明了训练数据矩阵的每列对应到一个样本;
//_responsens是各样本对应的类标签;_var_idx是特征索引(序号),_sample_idx是样本索引,_var_type在这里表示按特征响应排序;_missing_mask不知何意;
//_params保存训练得到的检测器;_update为false。这里使用CvBoost.tree->train()函数训练每一个弱分类器
//
    bool ok = false;
    CvMemStorage* storage = 0;

CV_FUNCNAME( "CvBoost::train" );

__BEGIN__;

int i;

set_params( _params );//初始化检测器参数

cvReleaseMat( &active_vars );
    cvReleaseMat( &active_vars_abs );

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/b28fd9f04c615ef47ca5ae9f988b73c3.html