本内容的源码在opencv开源源码的........\opencv\sources\apps\haartraining\cvhaartraining.cpp文件中,其他有关结构体,宏,函数指针的信息请参考http://blog.csdn.net/ding977921830/article/details/46799043。具体内容如下:
/* consumed counter */
typedef uint64 ccounter_t;
//含义无符号整形最大值
#define CCOUNTER_MAX CV_BIG_UINT(0xffffffffffffffff)
//把括号内参数清零
#define CCOUNTER_SET_ZERO(cc) ((cc) = 0)
//cc自加1
#define CCOUNTER_INC(cc) ( (CCOUNTER_MAX > (cc) ) ? (++(cc)) : (CCOUNTER_MAX) )
//二者之和
#define CCOUNTER_ADD(cc0, cc1) ( ((CCOUNTER_MAX-(cc1)) > (cc0) ) ? ((cc0) += (cc1)) : ((cc0) = CCOUNTER_MAX) )
//二者之除
#define CCOUNTER_DIV(cc0, cc1) ( ((cc1) == 0) ? 0 : ( ((double)(cc0))/(double)(int64)(cc1) ) )
/*
* icvGetHaarTrainingData
*计算从first开始共count个样本的haar特征值,并最后返回实际取出的haar特征值的个数
* Unified method that can now be used for vec file, bg file and bg vec file
*
* Fill <data> with samples, passed <cascade>
*/
static
int icvGetHaarTrainingData( CvHaarTrainingData* data,
int first, int count, //计算从first开始的共count个训练样本的特征值
CvIntHaarClassifier* cascade, //计算haar特征值的haar分类器
CvGetHaarTrainingDataCallback callback,
void* userdata, //训练样本数据和haar特征数据
int* consumed, //查询过的正样本总数
double* acceptance_ratio ) //实际取出的haar特征数与查询过的haar特征数之比
{
int i = 0;
ccounter_t getcount = 0; //实际取出的haar特征值的总数
ccounter_t thread_getcount = 0; //在程序中计算实际取出的haar特征值的总数
ccounter_t consumed_count; //查询过的haar特征总数
ccounter_t thread_consumed_count;//在程序中计算查询过的haar特征总数
/* private variables */
CvMat img; //源图像
CvMat sum; //积分图
CvMat tilted; //旋转积分图
CvMat sqsum; //像素平方的积分图
sum_type* sumdata;
sum_type* tilteddata;
float* normfactor;
/* end private variables */
assert( data != NULL );
assert( first + count <= data->maxnum );
assert( cascade != NULL );
assert( callback != NULL );
// if( !cvbgdata ) return 0; this check needs to be done in the callback for BG
//清零
CCOUNTER_SET_ZERO(getcount);
CCOUNTER_SET_ZERO(thread_getcount);
CCOUNTER_SET_ZERO(consumed_count);
CCOUNTER_SET_ZERO(thread_consumed_count);
#ifdef CV_OPENMP
#pragma omp parallel private(img, sum, tilted, sqsum, sumdata, tilteddata, \
normfactor, thread_consumed_count, thread_getcount)
#endif /* CV_OPENMP */
{
sumdata = NULL;
tilteddata = NULL;
normfactor = NULL;
CCOUNTER_SET_ZERO(thread_getcount);
CCOUNTER_SET_ZERO(thread_consumed_count);
int ok = 1;
//确定img,sum,tilted和sqsum的大小,并分配内存
img = cvMat( data->winsize.height, data->winsize.width, CV_8UC1,
cvAlloc( sizeof( uchar ) * data->winsize.height * data->winsize.width ) );
sum = cvMat( data->winsize.height + 1, data->winsize.width + 1,
CV_SUM_MAT_TYPE, NULL );
tilted = cvMat( data->winsize.height + 1, data->winsize.width + 1,
CV_SUM_MAT_TYPE, NULL );
sqsum = cvMat( data->winsize.height + 1, data->winsize.width + 1, CV_SQSUM_MAT_TYPE,
cvAlloc( sizeof( sqsum_type ) * (data->winsize.height + 1)
* (data->winsize.width + 1) ) );
#ifdef CV_OPENMP
#pragma omp for schedule(static, 1)
#endif /* CV_OPENMP */
for( i = first; (i < first + count); i++ )//遍历从first开始的共count个样本
{
if( !ok )
continue;
for( ; ; )
{
ok = callback( &img, userdata );
if( !ok )
break;
CCOUNTER_INC(thread_consumed_count);//查询过的haar特征总数
//在data中,每个样本的积分图占用一行,所以第i个样本的积分图为(sum_type*) (data->sum.data.ptr + i * data->sum.step)
//把data中的积分图的数据进行传递
sumdata = (sum_type*) (data->sum.data.ptr + i * data->sum.step);
tilteddata = (sum_type*) (data->tilted.data.ptr + i * data->tilted.step);
normfactor = data->normfactor.data.fl + i;
//把从data中提取出的数据存储到sum和tilted中
sum.data.ptr = (uchar*) sumdata;
tilted.data.ptr = (uchar*) tilteddata;
icvGetAuxImages( &img, &sum, &tilted, &sqsum, normfactor );//根据img图像计算积分图,旋转积分图,平方积分图和归一化因子
//如果计算出来的haar特征值不为0
if( cascade->eval( cascade, sumdata, tilteddata, *normfactor ) != 0.0F )
{
CCOUNTER_INC(thread_getcount);//从这里可以看出来thread_getcount的含义是这count个样本所有的有效的haar特征值的个数
break;
}
}
#ifdef CV_VERBOSE
if( (i - first) % 500 == 0 )
{
fprintf( stderr, "%3d%%\r", (int) ( 100.0 * (i - first) / count ) );
fflush( stderr );
}
#endif /* CV_VERBOSE */
}
cvFree( &(img.data.ptr) );
cvFree( &(sqsum.data.ptr) );
#ifdef CV_OPENMP
#pragma omp critical (c_consumed_count)
#endif /* CV_OPENMP */
{
/* consumed_count += thread_consumed_count; */
CCOUNTER_ADD(getcount, thread_getcount); //得到的有效haar特征值的总数
CCOUNTER_ADD(consumed_count, thread_consumed_count);
}
} /* omp parallel */
if( consumed != NULL )
{
*consumed = (int)consumed_count;
}
if( acceptance_ratio != NULL )
{
/* *acceptance_ratio = ((double) count) / consumed_count; */
*acceptance_ratio = CCOUNTER_DIV(count, consumed_count);
}
return static_cast<int>(getcount);
}