Skip to content

Instantly share code, notes, and snippets.

@cou929
Created June 20, 2010 23:25
Show Gist options
  • Save cou929/446214 to your computer and use it in GitHub Desktop.
Save cou929/446214 to your computer and use it in GitHub Desktop.
CV_IMPL int
cvRunHaarClassifierCascade( const CvHaarClassifierCascade* _cascade,
CvPoint pt, int start_stage )
{
int result = -1;
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 )
return -1;
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 );
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 )
return 0;
ptr = ptr->next;
}
}
}
else if( cascade->is_stump_based )
{
for( i = start_stage; i < cascade->count; i++ )
{
#ifndef CV_HAAR_USE_SSE
double stage_sum = 0;
#else
__m128d stage_sum = _mm_setzero_pd();
#endif
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;
#ifndef CV_HAAR_USE_SSE
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;
stage_sum += classifier->alpha[sum >= t];
#else
// ayasin - NHM perf optim. Avoid use of costly flaky jcc
__m128d t = _mm_set_sd(node->threshold*variance_norm_factor);
__m128d a = _mm_set_sd(classifier->alpha[0]);
__m128d b = _mm_set_sd(classifier->alpha[1]);
__m128d sum = _mm_set_sd(calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight +
calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight);
t = _mm_cmpgt_sd(t, sum);
stage_sum = _mm_add_sd(stage_sum, _mm_blendv_pd(b, a, t));
#endif
}
}
else
{
for( j = 0; j < cascade->stage_classifier[i].count; j++ )
{
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
CvHidHaarTreeNode* node = classifier->node;
#ifndef CV_HAAR_USE_SSE
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;
if( node->feature.rect[2].p0 )
sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight;
stage_sum += classifier->alpha[sum >= t];
#else
// ayasin - NHM perf optim. Avoid use of costly flaky jcc
__m128d t = _mm_set_sd(node->threshold*variance_norm_factor);
__m128d a = _mm_set_sd(classifier->alpha[0]);
__m128d b = _mm_set_sd(classifier->alpha[1]);
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;
if( node->feature.rect[2].p0 )
_sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight;
__m128d sum = _mm_set_sd(_sum);
t = _mm_cmpgt_sd(t, sum);
stage_sum = _mm_add_sd(stage_sum, _mm_blendv_pd(b, a, t));
#endif
}
}
#ifndef CV_HAAR_USE_SSE
if( stage_sum < cascade->stage_classifier[i].threshold )
#else
__m128d i_threshold = _mm_set_sd(cascade->stage_classifier[i].threshold);
if( _mm_comilt_sd(stage_sum, i_threshold) )
#endif
return -i;
}
}
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 )
return -i;
}
}
return 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment