for( i = 0; i < max_threads; i++ )
{
if( seq_thread[i] )
cvReleaseMemStorage( &seq_thread[i]->storage ); //如果使用了OpenMP就释放使用的seq_thread
}
#endif
cvReleaseMemStorage( &temp_storage );
cvReleaseMat( &sum );
cvReleaseMat( &sqsum );
cvReleaseMat( &tilted ); //释放使用的空间
cvReleaseMat( &temp );
cvReleaseMat( &sumcanny );
cvReleaseMat( &norm_img );
cvReleaseMat( &img_small );
cvFree( &comps );
return result_seq; //返回结果
}
下面是cvRunHaarClassifierCascade的:
CV_IMPL int
cvRunHaarClassifierCascade( CvHaarClassifierCascade* _cascade,
CvPoint pt, int start_stage )
{
int result = -1;
CV_FUNCNAME(”cvRunHaarClassifierCascade”);
__BEGIN__;
int p_offset, pq_offset;
int i, j;
double mean, variance_norm_factor;
CvHidHaarClassifierCascade* cascade;
if( !CV_IS_HAAR_CLASSIFIER(_cascade) )
CV_ERROR( !_cascade ? CV_StsNullPtr : CV_StsBadArg, “Invalid cascade pointer” );
cascade = _cascade->hid_cascade;
if( !cascade )
CV_ERROR( CV_StsNullPtr, “Hidden cascade has not been created.\n”
“Use cvSetImagesForHaarClassifierCascade” );
if( pt.x < 0 || pt.y < 0 ||
pt.x + _cascade->real_window_size.width >= cascade->sum.width-2 ||
pt.y + _cascade->real_window_size.height >= cascade->sum.height-2 ) //超边退出
EXIT;
p_offset = pt.y * (cascade->sum.step/sizeof(sumtype)) + pt.x;
pq_offset = pt.y * (cascade->sqsum.step/sizeof(sqsumtype)) + pt.x;
mean = calc_sum(*cascade,p_offset)*cascade->inv_window_area;
variance_norm_factor = cascade->pq0[pq_offset] – cascade->pq1[pq_offset] - //左上+右下-右上-左下
cascade->pq2[pq_offset] + cascade->pq3[pq_offset];
variance_norm_factor = variance_norm_factor*cascade->inv_window_area – mean*mean;
if( variance_norm_factor >= 0. )
variance_norm_factor = sqrt(variance_norm_factor);
else
variance_norm_factor = 1.;
if( cascade->is_tree ) //是树形的分类器,就按照层来匹配.
{
CvHidHaarStageClassifier* ptr;
assert( start_stage == 0 ); //start_stage==0继续
result = 1;
ptr = cascade->stage_classifier;
while( ptr )
{
double stage_sum = 0;
for( j = 0; j < ptr->count; j++ )
{
stage_sum += icvEvalHidHaarClassifier( ptr->classifier + j, //层判断
variance_norm_factor, p_offset );
}
if( stage_sum >= ptr->threshold )
{
ptr = ptr->child; //层判断通过,到下一层.
}
else
{
while( ptr && ptr->next == NULL ) ptr = ptr->parent; //未通过,且当前子分类器没有同层分类器,没有返回上层
if( ptr == NULL ) //如果刚才已经是最顶层了.
{
result = 0; //返回0,退出.
EXIT;
}
ptr = ptr->next; //指向下一个分类器.
}
}
}
else if( cascade->is_stump_based ) //如果是stump类的分类器
{
for( i = start_stage; i < cascade->count; i++ )
{
double stage_sum = 0;
if( cascade->stage_classifier[i].two_rects )
{
for( j = 0; j < cascade->stage_classifier[i].count; j++ )
{
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
CvHidHaarTreeNode* node = classifier->node;
double sum, t = node->threshold*variance_norm_factor, a, b;
sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
a = classifier->alpha[0];
b = classifier->alpha[1];
stage_sum += sum < t ? a : b;
}
}
else
{
for( j = 0; j < cascade->stage_classifier[i].count; j++ )
{
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
CvHidHaarTreeNode* node = classifier->node;
double sum, t = node->threshold*variance_norm_factor, a, b;
sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
if( node->feature.rect[2].p0 )
sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight;
a = classifier->alpha[0];
b = classifier->alpha[1];
stage_sum += sum < t ? a : b;
}
}
if( stage_sum < cascade->stage_classifier[i].threshold )
{ //没通过.则返回负的没通过的分类器数.
result = -i;
EXIT;
}
}
}
else //如果不是那两种强分类器
{
for( i = start_stage; i < cascade->count; i++ )
{
double stage_sum = 0;
for( j = 0; j < cascade->stage_classifier[i].count; j++ )
{
stage_sum += icvEvalHidHaarClassifier(
cascade->stage_classifier[i].classifier + j,
variance_norm_factor, p_offset );
}
if( stage_sum < cascade->stage_classifier[i].threshold )
{
result = -i;
EXIT;
}
}
}
result = 1;
__END__;
return result; //返回结果
}
double mean, variance_norm_factor; CvHidHaarClassifierCascade* cascade; if( !CV_IS_HAAR_CLASSIFIER(_cascade) )
CV_ERROR( !_cascade ? CV_StsNullPtr : CV_StsBadArg, “Invalid cascade pointer” );
cascade = _cascade->hid_cascade; if( !cascade )
CV_ERROR( CV_StsNullPtr, “Hidden cascade has not been created.\n”
“Use cvSetImagesForHaarClassifierCascade” ); if( pt.x < 0 || pt.y < 0 ||
pt.x + _cascade->real_window_size.width >= cascade->sum.width-2 ||
pt.y + _cascade->real_window_size.height >= cascade->sum.height-2 ) //超边退出 EXIT;
p_offset = pt.y * (cascade->sum.step/sizeof(sumtype)) + pt.x; pq_offset = pt.y * (cascade->sqsum.step/sizeof(sqsumtype)) + pt.x;
mean = calc_sum(*cascade,p_offset)*cascade->inv_window_area; variance_norm_factor = cascade->pq0[pq_offset] – cascade->pq1[pq_offset] - //左上+右下-右上-左下 cascade->pq2[pq_offset] + cascade->pq3[pq_offset]; variance_norm_factor =
variance_norm_factor*cascade->inv_window_area – mean*mean; if( variance_norm_factor >= 0. )
variance_norm_factor = sqrt(variance_norm_factor); else
variance_norm_factor = 1.;
if( cascade->is_tree ) //是树形的分类器,就按照层来匹配. {
CvHidHaarStageClassifier* ptr;
assert( start_stage == 0 ); //start_stage==0继续 result = 1;
ptr = cascade->stage_classifier; while( ptr ) {
double stage_sum = 0;
for( j = 0; j < ptr->count; j++ ) { stage_sum +=
icvEvalHidHaarClassifier( ptr->classifier + j, //层判断 variance_norm_factor, p_offset ); }
if( stage_sum >= ptr->threshold ) {
ptr = ptr->child; //层判断通过,到下一层. } else {
while( ptr && ptr->next == NULL ) ptr =
ptr->parent; //未通过,且当前子分类器没有同层分类器,没有返回上层 if( ptr == NULL ) //如果刚才已经是最顶层了. {
result = 0; //返回0,退出. EXIT; }
ptr = ptr->next; //指向下一个分类器. } }
}
else if( cascade->is_stump_based ) //如果是stump类的分类器 {
for( i = start_stage; i < cascade->count; i++ ) {
double stage_sum = 0;
if( cascade->stage_classifier[i].two_rects ) {
for( j = 0; j < cascade->stage_classifier[i].count; j++ ) {
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
CvHidHaarTreeNode* node = classifier->node;
double sum, t = node->threshold*variance_norm_factor, a, b;
sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; a = classifier->alpha[0]; b = classifier->alpha[1]; stage_sum += sum < t ? a : b; } } else {
for( j = 0; j < cascade->stage_classifier[i].count; j++ ) {
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
CvHidHaarTreeNode* node = classifier->node;
double sum, t = node->threshold*variance_norm_factor, a, b;
sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
if( node->feature.rect[2].p0 )
sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; a = classifier->alpha[0]; b = classifier->alpha[1]; stage_sum += sum < t ? a : b; } }
if( stage_sum < cascade->stage_classifier[i].threshold ) { //没通过.则返回负的没通过的分类器数. result = -i; EXIT; } } }
else //如果不是那两种强分类器 {
for( i = start_stage; i < cascade->count; i++ ) {
double stage_sum = 0;
for( j = 0; j < cascade->stage_classifier[i].count; j++ ) {
stage_sum += icvEvalHidHaarClassifier(
cascade->stage_classifier[i].classifier + j, variance_norm_factor, p_offset ); }
if( stage_sum < cascade->stage_classifier[i].threshold ) {
result = -i;
EXIT; } } }
result = 1; __END__;
return result; //返回结果 }
double mean, variance_norm_factor; CvHidHaarClassifierCascade* cascade; if( !CV_IS_HAAR_CLASSIFIER(_cascade) )
CV_ERROR( !_cascade ? CV_StsNullPtr : CV_StsBadArg, “Invalid cascade pointer” );
cascade = _cascade->hid_cascade; if( !cascade )
CV_ERROR( CV_StsNullPtr, “Hidden cascade has not been created.\n”
“Use cvSetImagesForHaarClassifierCascade” ); if( pt.x < 0 || pt.y < 0 ||
pt.x + _cascade->real_window_size.width >= cascade->sum.width-2 ||
pt.y + _cascade->real_window_size.height >= cascade->sum.height-2 ) //超边退出 EXIT;
p_offset = pt.y * (cascade->sum.step/sizeof(sumtype)) + pt.x; pq_offset = pt.y * (cascade->sqsum.step/sizeof(sqsumtype)) + pt.x;
mean = calc_sum(*cascade,p_offset)*cascade->inv_window_area; variance_norm_factor = cascade->pq0[pq_offset] – cascade->pq1[pq_offset] - //左上+右下-右上-左下 cascade->pq2[pq_offset] + cascade->pq3[pq_offset]; variance_norm_factor =
variance_norm_factor*cascade->inv_window_area – mean*mean; if( variance_norm_factor >= 0. )
variance_norm_factor = sqrt(variance_norm_factor); else
variance_norm_factor = 1.;
if( cascade->is_tree ) //是树形的分类器,就按照层来匹配. {
CvHidHaarStageClassifier* ptr;
assert( start_stage == 0 ); //start_stage==0继续 result = 1;
ptr = cascade->stage_classifier; while( ptr ) {
double stage_sum = 0;
for( j = 0; j < ptr->count; j++ ) { stage_sum +=
icvEvalHidHaarClassifier( ptr->classifier + j, //层判断 variance_norm_factor, p_offset ); }
if( stage_sum >= ptr->threshold ) {
ptr = ptr->child; //层判断通过,到下一层. } else {
while( ptr && ptr->next == NULL ) ptr =
ptr->parent; //未通过,且当前子分类器没有同层分类器,没有返回上层 if( ptr == NULL ) //如果刚才已经是最顶层了. {
result = 0; //返回0,退出. EXIT; }
ptr = ptr->next; //指向下一个分类器. } }
}
else if( cascade->is_stump_based ) //如果是stump类的分类器 {
for( i = start_stage; i < cascade->count; i++ ) {
double stage_sum = 0;
if( cascade->stage_classifier[i].two_rects ) {
for( j = 0; j < cascade->stage_classifier[i].count; j++ ) {
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
CvHidHaarTreeNode* node = classifier->node;
double sum, t = node->threshold*variance_norm_factor, a, b;
sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; a = classifier->alpha[0]; b = classifier->alpha[1]; stage_sum += sum < t ? a : b; } } else {
for( j = 0; j < cascade->stage_classifier[i].count; j++ ) {
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
CvHidHaarTreeNode* node = classifier->node;
double sum, t = node->threshold*variance_norm_factor, a, b;
sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
if( node->feature.rect[2].p0 )
sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; a = classifier->alpha[0]; b = classifier->alpha[1]; stage_sum += sum < t ? a : b; } }
if( stage_sum < cascade->stage_classifier[i].threshold ) { //没通过.则返回负的没通过的分类器数. result = -i; EXIT; } } }
else //如果不是那两种强分类器 {
for( i = start_stage; i < cascade->count; i++ ) {
double stage_sum = 0;
for( j = 0; j < cascade->stage_classifier[i].count; j++ ) {
stage_sum += icvEvalHidHaarClassifier(
cascade->stage_classifier[i].classifier + j, variance_norm_factor, p_offset ); }
if( stage_sum < cascade->stage_classifier[i].threshold ) {
result = -i;
EXIT; } } }
result = 1; __END__;
return result; //返回结果 }
double mean, variance_norm_factor; CvHidHaarClassifierCascade* cascade; if( !CV_IS_HAAR_CLASSIFIER(_cascade) )
CV_ERROR( !_cascade ? CV_StsNullPtr : CV_StsBadArg, “Invalid cascade pointer” );
cascade = _cascade->hid_cascade; if( !cascade )
CV_ERROR( CV_StsNullPtr, “Hidden cascade has not been created.\n”
“Use cvSetImagesForHaarClassifierCascade” ); if( pt.x < 0 || pt.y < 0 ||
pt.x + _cascade->real_window_size.width >= cascade->sum.width-2 ||
pt.y + _cascade->real_window_size.height >= cascade->sum.height-2 ) //超边退出 EXIT;
p_offset = pt.y * (cascade->sum.step/sizeof(sumtype)) + pt.x; pq_offset = pt.y * (cascade->sqsum.step/sizeof(sqsumtype)) + pt.x;
mean = calc_sum(*cascade,p_offset)*cascade->inv_window_area; variance_norm_factor = cascade->pq0[pq_offset] – cascade->pq1[pq_offset] - //左上+右下-右上-左下 cascade->pq2[pq_offset] + cascade->pq3[pq_offset]; variance_norm_factor =
variance_norm_factor*cascade->inv_window_area – mean*mean; if( variance_norm_factor >= 0. )
variance_norm_factor = sqrt(variance_norm_factor); else
variance_norm_factor = 1.;
if( cascade->is_tree ) //是树形的分类器,就按照层来匹配. {
CvHidHaarStageClassifier* ptr;
assert( start_stage == 0 ); //start_stage==0继续 result = 1;
ptr = cascade->stage_classifier; while( ptr ) {
double stage_sum = 0;
for( j = 0; j < ptr->count; j++ ) { stage_sum +=
icvEvalHidHaarClassifier( ptr->classifier + j, //层判断 variance_norm_factor, p_offset ); }
if( stage_sum >= ptr->threshold ) {
ptr = ptr->child; //层判断通过,到下一层. } else {
while( ptr && ptr->next == NULL ) ptr =
ptr->parent; //未通过,且当前子分类器没有同层分类器,没有返回上层 if( ptr == NULL ) //如果刚才已经是最顶层了. {
result = 0; //返回0,退出. EXIT; }
ptr = ptr->next; //指向下一个分类器. } }
}
else if( cascade->is_stump_based ) //如果是stump类的分类器 {
for( i = start_stage; i < cascade->count; i++ ) {
double stage_sum = 0;
if( cascade->stage_classifier[i].two_rects ) {
for( j = 0; j < cascade->stage_classifier[i].count; j++ ) {
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
CvHidHaarTreeNode* node = classifier->node;
double sum, t = node->threshold*variance_norm_factor, a, b;
sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; a = classifier->alpha[0]; b = classifier->alpha[1]; stage_sum += sum < t ? a : b; } } else {
for( j = 0; j < cascade->stage_classifier[i].count; j++ ) {
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
CvHidHaarTreeNode* node = classifier->node;
double sum, t = node->threshold*variance_norm_factor, a, b;
sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
if( node->feature.rect[2].p0 )
sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; a = classifier->alpha[0]; b = classifier->alpha[1]; stage_sum += sum < t ? a : b; } }
if( stage_sum < cascade->stage_classifier[i].threshold ) { //没通过.则返回负的没通过的分类器数. result = -i; EXIT; } } }
else //如果不是那两种强分类器 {
for( i = start_stage; i < cascade->count; i++ ) {
double stage_sum = 0;
for( j = 0; j < cascade->stage_classifier[i].count; j++ ) {
stage_sum += icvEvalHidHaarClassifier(
cascade->stage_classifier[i].classifier + j, variance_norm_factor, p_offset ); }
if( stage_sum < cascade->stage_classifier[i].threshold ) {
result = -i;
EXIT; } } }
result = 1; __END__;
return result; //返回结果 }
double mean, variance_norm_factor; CvHidHaarClassifierCascade* cascade; if( !CV_IS_HAAR_CLASSIFIER(_cascade) )
CV_ERROR( !_cascade ? CV_StsNullPtr : CV_StsBadArg, “Invalid cascade pointer” );
cascade = _cascade->hid_cascade; if( !cascade )
CV_ERROR( CV_StsNullPtr, “Hidden cascade has not been created.\n”
“Use cvSetImagesForHaarClassifierCascade” ); if( pt.x < 0 || pt.y < 0 ||
pt.x + _cascade->real_window_size.width >= cascade->sum.width-2 ||
pt.y + _cascade->real_window_size.height >= cascade->sum.height-2 ) //超边退出 EXIT;
p_offset = pt.y * (cascade->sum.step/sizeof(sumtype)) + pt.x; pq_offset = pt.y * (cascade->sqsum.step/sizeof(sqsumtype)) + pt.x;
mean = calc_sum(*cascade,p_offset)*cascade->inv_window_area; variance_norm_factor = cascade->pq0[pq_offset] – cascade->pq1[pq_offset] - //左上+右下-右上-左下 cascade->pq2[pq_offset] + cascade->pq3[pq_offset]; variance_norm_factor =
variance_norm_factor*cascade->inv_window_area – mean*mean; if( variance_norm_factor >= 0. )
variance_norm_factor = sqrt(variance_norm_factor); else
variance_norm_factor = 1.;
if( cascade->is_tree ) //是树形的分类器,就按照层来匹配. {
CvHidHaarStageClassifier* ptr;
assert( start_stage == 0 ); //start_stage==0继续 result = 1;
ptr = cascade->stage_classifier; while( ptr ) {
double stage_sum = 0;
for( j = 0; j < ptr->count; j++ ) { stage_sum +=
icvEvalHidHaarClassifier( ptr->classifier + j, //层判断 variance_norm_factor, p_offset ); }
if( stage_sum >= ptr->threshold ) {
ptr = ptr->child; //层判断通过,到下一层. } else {
while( ptr && ptr->next == NULL ) ptr =
ptr->parent; //未通过,且当前子分类器没有同层分类器,没有返回上层 if( ptr == NULL ) //如果刚才已经是最顶层了. {
result = 0; //返回0,退出. EXIT; }
ptr = ptr->next; //指向下一个分类器. } }
}
else if( cascade->is_stump_based ) //如果是stump类的分类器 {
for( i = start_stage; i < cascade->count; i++ ) {
double stage_sum = 0;
if( cascade->stage_classifier[i].two_rects ) {
for( j = 0; j < cascade->stage_classifier[i].count; j++ ) {
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
CvHidHaarTreeNode* node = classifier->node;
double sum, t = node->threshold*variance_norm_factor, a, b;
sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; a = classifier->alpha[0]; b = classifier->alpha[1]; stage_sum += sum < t ? a : b; } } else {
for( j = 0; j < cascade->stage_classifier[i].count; j++ ) {
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
CvHidHaarTreeNode* node = classifier->node;
double sum, t = node->threshold*variance_norm_factor, a, b;
sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
if( node->feature.rect[2].p0 )
sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; a = classifier->alpha[0]; b = classifier->alpha[1]; stage_sum += sum < t ? a : b; } }
if( stage_sum < cascade->stage_classifier[i].threshold ) { //没通过.则返回负的没通过的分类器数. result = -i; EXIT; } } }
else //如果不是那两种强分类器 {
for( i = start_stage; i < cascade->count; i++ ) {
double stage_sum = 0;
for( j = 0; j < cascade->stage_classifier[i].count; j++ ) {
stage_sum += icvEvalHidHaarClassifier(
cascade->stage_classifier[i].classifier + j, variance_norm_factor, p_offset ); }
if( stage_sum < cascade->stage_classifier[i].threshold ) {
result = -i;
EXIT; } } }
result = 1; __END__;
return result; //返回结果 }