//do_train()的核心函数如下:
CvDTreeNode* CvDTreeTrainData::subsample_data( const CvMat* _subsample_idx )
{
CvDTreeNode* root = 0;
CvMat* isubsample_idx = 0;
CvMat* subsample_co = 0;
bool isMakeRootCopy = true;
CV_FUNCNAME( "CvDTreeTrainData::subsample_data" );
__BEGIN__;
if( !data_root )
CV_ERROR( CV_StsError, "No training data has been set" );
if( _subsample_idx )
{
CV_CALL( isubsample_idx = cvPreprocessIndexArray( _subsample_idx, sample_count )); //如果已训练出了一些弱分类器,则在这里进行一定的处理。_subsample_idx只能是一个行向量或者是列向量
//_subsample_idx中保存的可能是选中的样本的索引,也可能长度为sample_count的表明选择的'0''1'掩膜,但
//输出只包含了选择的样本的编号,并且进行了排序。
if( isubsample_idx->cols + isubsample_idx->rows - 1 == sample_count ) //isubsample_idx是一个指向行向量或者列向量的指针,这里验证元素个数与样本数是否相等。
{
const int* sidx = isubsample_idx->data.i;
for( int i = 0; i < sample_count; i++ )
{
if( sidx[i] != i )
{
isMakeRootCopy = false; //若尚无任何弱分类器,则'isMakeRootCopy = true',
break;
}
}
}
else
isMakeRootCopy = false;
}
if( isMakeRootCopy )
{
// make a copy of the root node
CvDTreeNode temp;
int i;
root = new_node( 0, 1, 0, 0 );
temp = *root;
*root = *data_root;
root->num_valid = temp.num_valid;
if( root->num_valid )
{
for( i = 0; i < var_count; i++ )
root->num_valid[i] = data_root->num_valid[i];
}
root->cv_Tn = temp.cv_Tn;
root->cv_node_risk = temp.cv_node_risk;
root->cv_node_error = temp.cv_node_error;
}
else
{
int* sidx = isubsample_idx->data.i;
// co - array of count/offset pairs (to handle duplicated values in _subsample_idx)
int* co, cur_ofs = 0;
int vi, i;
int workVarCount = get_work_var_count(); //得到已使用的特征个数?
int count = isubsample_idx->rows + isubsample_idx->cols - 1; //该弱分类器判断为正的样本个数
root = new_node( 0, count, 1, 0 );
CV_CALL( subsample_co = cvCreateMat( 1, sample_count*2, CV_32SC1 ));
cvZero( subsample_co );
co = subsample_co->data.i;
for( i = 0; i < count; i++ )
co[sidx[i]*2]++;
for( i = 0; i < sample_count; i++ )
{
if( co[i*2] )
{
co[i*2+1] = cur_ofs;
cur_ofs += co[i*2];
}
else
co[i*2+1] = -1;
}
cv::AutoBuffer<uchar> inn_buf(sample_count*(2*sizeof(int) + sizeof(float)));
for( vi = 0; vi < workVarCount; vi++ )
{
int ci = get_var_type(vi);