icvGetTrainingDataCallback源码详细分析

cvUsedata的内容请参考我的另外一篇博文http://blog.csdn.net/ding977921830/article/details/46868313。转载请注明本博网址http://blog.csdn.net/ding977921830/article/details/46867757


/*
*函数icvGetTrainingDataCallback介绍
*功能:计算特征值,具体来说也就是,根据训练样本信息和特征信息,对所有样本计算特征编号从first开始的num个特征,并保存到mat里。
*输入:
*CvMat* mat矩阵样本总数个行,num个列。保存每个样本的num个特征值。
*First:特征类型编号的开始处
*Num:要计算的特征类型个数。
*Userdata:训练样本信息和特征信息,包括积分矩阵和权重、特征模板等信息。
*输出:
*CvMat* mat矩阵样本总数个行,num个列。保存每个样本的num个特征值。
*部分内容参考http://www.opencvchina.com/thread-200-1-1.html。
 */
static
void icvGetTrainingDataCallback( CvMat* mat, CvMat* sampleIdx, CvMat*,
                                 int first, int num, void* userdata )
{
    int i = 0;
    int j = 0;
    float val = 0.0F;
    float normfactor = 0.0F;

    CvHaarTrainingData* training_data;  //存储训练样本信息
    CvIntHaarFeatures* haar_features;   //存储特征信息

#ifdef CV_COL_ARRANGEMENT
    assert( mat->rows >= num );
#else
    assert( mat->cols >= num );
#endif
	//userdata = cvUserdata( data, haarFeatures )
	//userdata包含了参与训练的积分图和特征,其指针应该是用于回调的用户参数
    training_data = ((CvUserdata*) userdata)->trainingData;
    haar_features = ((CvUserdata*) userdata)->haarFeatures;
    if( sampleIdx == NULL )                                      //当sampleIdx为空时,需要的训练样本数量以mat的大小为准
    {
        int num_samples;

#ifdef CV_COL_ARRANGEMENT
        num_samples = mat->cols;
#else
        num_samples = mat->rows;
#endif 
        for( i = 0; i < num_samples; i++ )                        //遍历所有样本
        {
            for( j = 0; j < num; j++ )                            //遍历从first开始的num个特征
            {   //根据积分图来计算特征的特征值,我认为本质上是根据训练样本信息和特征信息来共同计算
                val = cvEvalFastHaarFeature(
                        ( haar_features->fastfeature
                            + first + j ),                       //确定是计算的哪个特征,也就是第first+j个特征
                        (sum_type*) (training_data->sum.data.ptr
                            + i * training_data->sum.step),      //因为每个图片的积分图是按行排列的,所以第i个样本的积分图要这样计算
                        (sum_type*) (training_data->tilted.data.ptr
                            + i * training_data->tilted.step) );
                normfactor = training_data->normfactor.data.fl[i];
                val = ( normfactor == 0.0F ) ? 0.0F : (val / normfactor);//根据缩放因子来调整特征值的大小

#ifdef CV_COL_ARRANGEMENT
                CV_MAT_ELEM( *mat, float, j, i ) = val;          //根据是按行排列还是按列排列来存储计算好的特征值val
#else
                CV_MAT_ELEM( *mat, float, i, j ) = val;
#endif
            }
        }
    }
    else                                                        //当sampleIdx不为空时,需要的训练样本数量以sampleIdx中的信息为准
    {
        uchar* idxdata = NULL;
        size_t step    = 0;
        int    numidx  = 0;
        int    idx     = 0;

        assert( CV_MAT_TYPE( sampleIdx->type ) == CV_32FC1 );

        idxdata = sampleIdx->data.ptr;                         //把sampleIdx中样本的数据信息指向idxdata
        if( sampleIdx->rows == 1 )                             //根据sampleIdx是否为一行来确定训练样本的数量和一个样本所占的步长step
        {
            step = sizeof( float );
            numidx = sampleIdx->cols;
        }
        else
        {
            step = sampleIdx->step;
            numidx = sampleIdx->rows;
        }

        for( i = 0; i < numidx; i++ )
        {
            for( j = 0; j < num; j++ )
            {
                idx = (int)( *((float*) (idxdata + i * step)) );
                /*这里与上面求val不同的是,需要求一个idx,也就是需要知道是要求的第几个训练样本序号,因为在sampleIdx中训练样本并不一定是按顺
                  序排列的,但是在计算好的积分图中,所有训练样本的积分图都是严格排列的。那么,我们要计算的第numidx个样本的第j个特征的特征值
                  就需要先求出它在积分图中是第idx个样本的序号*/
                 val = cvEvalFastHaarFeature(
                        ( haar_features->fastfeature
                            + first + j ),
                        (sum_type*) (training_data->sum.data.ptr
                            + idx * training_data->sum.step),
                        (sum_type*) (training_data->tilted.data.ptr
                            + idx * training_data->tilted.step) );
                normfactor = training_data->normfactor.data.fl[idx];
                val = ( normfactor == 0.0F ) ? 0.0F : (val / normfactor);

#ifdef CV_COL_ARRANGEMENT
                CV_MAT_ELEM( *mat, float, j, idx ) = val;
#else
                CV_MAT_ELEM( *mat, float, idx, j ) = val;
#endif

            }
        }
    }
#if 0 /*def CV_VERBOSE*/
    if( first % 5000 == 0 )
    {
        fprintf( stderr, "%3d%%\r", (int) (100.0 * first /
            haar_features->count) );
        fflush( stderr );
    }
#endif /* CV_VERBOSE */
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值