您的位置:首页 > 大数据 > 人工智能

icvGetTrainingDataCallback源码详细分析

2015-07-13 21:50 489 查看
cvUsedata的内容请参考我的另外一篇博文/article/9786789.html。转载请注明本博网址/article/9786787.html

/*
*函数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 */
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: