📄 cvhaar.cpp
字号:
{
int can_use_ipp = icvHaarClassifierInitAlloc_32f_p != 0 &&
icvHaarClassifierFree_32f_p != 0 &&
icvApplyHaarClassifier_32s32f_C1R_p != 0 &&
icvRectStdDev_32s32f_C1R_p != 0 &&
!out->has_tilted_features && !out->is_tree && out->is_stump_based;
if( can_use_ipp )
{
int ipp_datasize = cascade->count*sizeof(out->ipp_stages[0]);
float ipp_weight_scale=(float)(1./((orig_window_size.width-icv_object_win_border*2)*
(orig_window_size.height-icv_object_win_border*2)));
CV_CALL( out->ipp_stages = (void**)cvAlloc( ipp_datasize ));
memset( out->ipp_stages, 0, ipp_datasize );
CV_CALL( ipp_features = (CvRect*)cvAlloc( max_count*3*sizeof(ipp_features[0]) ));
CV_CALL( ipp_weights = (float*)cvAlloc( max_count*3*sizeof(ipp_weights[0]) ));
CV_CALL( ipp_thresholds = (float*)cvAlloc( max_count*sizeof(ipp_thresholds[0]) ));
CV_CALL( ipp_val1 = (float*)cvAlloc( max_count*sizeof(ipp_val1[0]) ));
CV_CALL( ipp_val2 = (float*)cvAlloc( max_count*sizeof(ipp_val2[0]) ));
CV_CALL( ipp_counts = (int*)cvAlloc( max_count*sizeof(ipp_counts[0]) ));
for( i = 0; i < cascade->count; i++ )
{
CvHaarStageClassifier* stage_classifier = cascade->stage_classifier + i;
for( j = 0, k = 0; j < stage_classifier->count; j++ )
{
CvHaarClassifier* classifier = stage_classifier->classifier + j;
int rect_count = 2 + (classifier->haar_feature->rect[2].r.width != 0);
ipp_thresholds[j] = classifier->threshold[0];
ipp_val1[j] = classifier->alpha[0];
ipp_val2[j] = classifier->alpha[1];
ipp_counts[j] = rect_count;
for( l = 0; l < rect_count; l++, k++ )
{
ipp_features[k] = classifier->haar_feature->rect[l].r;
//ipp_features[k].y = orig_window_size.height - ipp_features[k].y - ipp_features[k].height;
ipp_weights[k] = classifier->haar_feature->rect[l].weight*ipp_weight_scale;
}
}
if( icvHaarClassifierInitAlloc_32f_p( &out->ipp_stages[i],
ipp_features, ipp_weights, ipp_thresholds,
ipp_val1, ipp_val2, ipp_counts, stage_classifier->count ) < 0 )
break;
}
if( i < cascade->count )
{
for( j = 0; j < i; j++ )
if( icvHaarClassifierFree_32f_p && out->ipp_stages[i] )
icvHaarClassifierFree_32f_p( out->ipp_stages[i] );
cvFree( &out->ipp_stages );
}
}
}
#endif
cascade->hid_cascade = out;
assert( (char*)haar_node_ptr - (char*)out <= datasize );
__END__;
if( cvGetErrStatus() < 0 )
icvReleaseHidHaarClassifierCascade( &out );
cvFree( &ipp_features );
cvFree( &ipp_weights );
cvFree( &ipp_thresholds );
cvFree( &ipp_val1 );
cvFree( &ipp_val2 );
cvFree( &ipp_counts );
return out;
}
#define sum_elem_ptr(sum,row,col) \
((sumtype*)CV_MAT_ELEM_PTR_FAST((sum),(row),(col),sizeof(sumtype)))
#define sqsum_elem_ptr(sqsum,row,col) \
((sqsumtype*)CV_MAT_ELEM_PTR_FAST((sqsum),(row),(col),sizeof(sqsumtype)))
#define calc_sum(rect,offset) \
((rect).p0[offset] - (rect).p1[offset] - (rect).p2[offset] + (rect).p3[offset])
CV_IMPL void
cvSetImagesForHaarClassifierCascade( CvHaarClassifierCascade* _cascade,
const CvArr* _sum,
const CvArr* _sqsum,
const CvArr* _tilted_sum,
double scale )
{
CV_FUNCNAME("cvSetImagesForHaarClassifierCascade");
__BEGIN__;
CvMat sum_stub, *sum = (CvMat*)_sum;
CvMat sqsum_stub, *sqsum = (CvMat*)_sqsum;
CvMat tilted_stub, *tilted = (CvMat*)_tilted_sum;
CvHidHaarClassifierCascade* cascade;
int coi0 = 0, coi1 = 0;
int i;
CvRect equ_rect;
double weight_scale;
if( !CV_IS_HAAR_CLASSIFIER(_cascade) )
CV_ERROR( !_cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier pointer" );
if( scale <= 0 )
CV_ERROR( CV_StsOutOfRange, "Scale must be positive" );
CV_CALL( sum = cvGetMat( sum, &sum_stub, &coi0 ));
CV_CALL( sqsum = cvGetMat( sqsum, &sqsum_stub, &coi1 ));
if( coi0 || coi1 )
CV_ERROR( CV_BadCOI, "COI is not supported" );
if( !CV_ARE_SIZES_EQ( sum, sqsum ))
CV_ERROR( CV_StsUnmatchedSizes, "All integral images must have the same size" );
if( CV_MAT_TYPE(sqsum->type) != CV_64FC1 ||
CV_MAT_TYPE(sum->type) != CV_32SC1 )
CV_ERROR( CV_StsUnsupportedFormat,
"Only (32s, 64f, 32s) combination of (sum,sqsum,tilted_sum) formats is allowed" );
if( !_cascade->hid_cascade )
CV_CALL( icvCreateHidHaarClassifierCascade(_cascade) );
cascade = _cascade->hid_cascade;
if( cascade->has_tilted_features )
{
CV_CALL( tilted = cvGetMat( tilted, &tilted_stub, &coi1 ));
if( CV_MAT_TYPE(tilted->type) != CV_32SC1 )
CV_ERROR( CV_StsUnsupportedFormat,
"Only (32s, 64f, 32s) combination of (sum,sqsum,tilted_sum) formats is allowed" );
if( sum->step != tilted->step )
CV_ERROR( CV_StsUnmatchedSizes,
"Sum and tilted_sum must have the same stride (step, widthStep)" );
if( !CV_ARE_SIZES_EQ( sum, tilted ))
CV_ERROR( CV_StsUnmatchedSizes, "All integral images must have the same size" );
cascade->tilted = *tilted;
}
_cascade->scale = scale;
_cascade->real_window_size.width = cvRound( _cascade->orig_window_size.width * scale );
_cascade->real_window_size.height = cvRound( _cascade->orig_window_size.height * scale );
cascade->sum = *sum;
cascade->sqsum = *sqsum;
equ_rect.x = equ_rect.y = cvRound(scale);
equ_rect.width = cvRound((_cascade->orig_window_size.width-2)*scale);
equ_rect.height = cvRound((_cascade->orig_window_size.height-2)*scale);
weight_scale = 1./(equ_rect.width*equ_rect.height);
cascade->inv_window_area = weight_scale;
cascade->p0 = sum_elem_ptr(*sum, equ_rect.y, equ_rect.x);
cascade->p1 = sum_elem_ptr(*sum, equ_rect.y, equ_rect.x + equ_rect.width );
cascade->p2 = sum_elem_ptr(*sum, equ_rect.y + equ_rect.height, equ_rect.x );
cascade->p3 = sum_elem_ptr(*sum, equ_rect.y + equ_rect.height,
equ_rect.x + equ_rect.width );
cascade->pq0 = sqsum_elem_ptr(*sqsum, equ_rect.y, equ_rect.x);
cascade->pq1 = sqsum_elem_ptr(*sqsum, equ_rect.y, equ_rect.x + equ_rect.width );
cascade->pq2 = sqsum_elem_ptr(*sqsum, equ_rect.y + equ_rect.height, equ_rect.x );
cascade->pq3 = sqsum_elem_ptr(*sqsum, equ_rect.y + equ_rect.height,
equ_rect.x + equ_rect.width );
/* init pointers in haar features according to real window size and
given image pointers */
{
#ifdef _OPENMP
int max_threads = cvGetNumThreads();
#pragma omp parallel for num_threads(max_threads), schedule(dynamic)
#endif // _OPENMP
for( i = 0; i < _cascade->count; i++ )
{
int j, k, l;
for( j = 0; j < cascade->stage_classifier[i].count; j++ )
{
for( l = 0; l < cascade->stage_classifier[i].classifier[j].count; l++ )
{
CvHaarFeature* feature =
&_cascade->stage_classifier[i].classifier[j].haar_feature[l];
/* CvHidHaarClassifier* classifier =
cascade->stage_classifier[i].classifier + j; */
CvHidHaarFeature* hidfeature =
&cascade->stage_classifier[i].classifier[j].node[l].feature;
double sum0 = 0, area0 = 0;
CvRect r[3];
#if CV_ADJUST_FEATURES
int base_w = -1, base_h = -1;
int new_base_w = 0, new_base_h = 0;
int kx, ky;
int flagx = 0, flagy = 0;
int x0 = 0, y0 = 0;
#endif
int nr;
/* align blocks */
for( k = 0; k < CV_HAAR_FEATURE_MAX; k++ )
{
if( !hidfeature->rect[k].p0 )
break;
#if CV_ADJUST_FEATURES
r[k] = feature->rect[k].r;
base_w = (int)CV_IMIN( (unsigned)base_w, (unsigned)(r[k].width-1) );
base_w = (int)CV_IMIN( (unsigned)base_w, (unsigned)(r[k].x - r[0].x-1) );
base_h = (int)CV_IMIN( (unsigned)base_h, (unsigned)(r[k].height-1) );
base_h = (int)CV_IMIN( (unsigned)base_h, (unsigned)(r[k].y - r[0].y-1) );
#endif
}
nr = k;
#if CV_ADJUST_FEATURES
base_w += 1;
base_h += 1;
kx = r[0].width / base_w;
ky = r[0].height / base_h;
if( kx <= 0 )
{
flagx = 1;
new_base_w = cvRound( r[0].width * scale ) / kx;
x0 = cvRound( r[0].x * scale );
}
if( ky <= 0 )
{
flagy = 1;
new_base_h = cvRound( r[0].height * scale ) / ky;
y0 = cvRound( r[0].y * scale );
}
#endif
for( k = 0; k < nr; k++ )
{
CvRect tr;
double correction_ratio;
#if CV_ADJUST_FEATURES
if( flagx )
{
tr.x = (r[k].x - r[0].x) * new_base_w / base_w + x0;
tr.width = r[k].width * new_base_w / base_w;
}
else
#endif
{
tr.x = cvRound( r[k].x * scale );
tr.width = cvRound( r[k].width * scale );
}
#if CV_ADJUST_FEATURES
if( flagy )
{
tr.y = (r[k].y - r[0].y) * new_base_h / base_h + y0;
tr.height = r[k].height * new_base_h / base_h;
}
else
#endif
{
tr.y = cvRound( r[k].y * scale );
tr.height = cvRound( r[k].height * scale );
}
#if CV_ADJUST_WEIGHTS
{
// RAINER START
const float orig_feature_size = (float)(feature->rect[k].r.width)*feature->rect[k].r.height;
const float orig_norm_size = (float)(_cascade->orig_window_size.width)*(_cascade->orig_window_size.height);
const float feature_size = float(tr.width*tr.height);
//const float normSize = float(equ_rect.width*equ_rect.height);
float target_ratio = orig_feature_size / orig_norm_size;
//float isRatio = featureSize / normSize;
//correctionRatio = targetRatio / isRatio / normSize;
correction_ratio = target_ratio / feature_size;
// RAINER END
}
#else
correction_ratio = weight_scale * (!feature->tilted ? 1 : 0.5);
#endif
if( !feature->tilted )
{
hidfeature->rect[k].p0 = sum_elem_ptr(*sum, tr.y, tr.x);
hidfeature->rect[k].p1 = sum_elem_ptr(*sum, tr.y, tr.x + tr.width);
hidfeature->rect[k].p2 = sum_elem_ptr(*sum, tr.y + tr.height, tr.x);
hidfeature->rect[k].p3 = sum_elem_ptr(*sum, tr.y + tr.height, tr.x + tr.width);
}
else
{
hidfeature->rect[k].p2 = sum_elem_ptr(*tilted, tr.y + tr.width, tr.x + tr.width);
hidfeature->rect[k].p3 = sum_elem_ptr(*tilted, tr.y + tr.width + tr.height,
tr.x + tr.width - tr.height);
hidfeature->rect[k].p0 = sum_elem_ptr(*tilted, tr.y, tr.x);
hidfeature->rect[k].p1 = sum_elem_ptr(*tilted, tr.y + tr.height, tr.x - tr.height);
}
hidfeature->rect[k].weight = (float)(feature->rect[k].weight * correction_ratio);
if( k == 0 )
area0 = tr.width * tr.height;
else
sum0 += hidfeature->rect[k].weight * tr.width * tr.height;
}
hidfeature->rect[0].weight = (float)(-sum0/area0);
} /* l */
} /* j */
}
}
__END__;
}
CV_INLINE
double icvEvalHidHaarClassifier( CvHidHaarClassifier* classifier,
double variance_norm_factor,
size_t p_offset )
{
int idx = 0;
do
{
CvHidHaarTreeNode* node = classifier->node + idx;
double t = node->threshold * variance_norm_factor;
double 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -