📄 cvhaar.cpp
字号:
if( node->feature.rect[2].p0 )
sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight;
idx = sum < t ? node->left : node->right;
}
while( idx > 0 );
return classifier->alpha[-idx];
}
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 );
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;
EXIT;
}
ptr = ptr->next;
}
}
}
else if( cascade->is_stump_based )
{
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;
}
static int is_equal( const void* _r1, const void* _r2, void* )
{
const CvRect* r1 = (const CvRect*)_r1;
const CvRect* r2 = (const CvRect*)_r2;
int distance = cvRound(r1->width*0.2);
return r2->x <= r1->x + distance &&
r2->x >= r1->x - distance &&
r2->y <= r1->y + distance &&
r2->y >= r1->y - distance &&
r2->width <= cvRound( r1->width * 1.2 ) &&
cvRound( r2->width * 1.2 ) >= r1->width;
}
CV_IMPL CvSeq*
cvHaarDetectObjects( const CvArr* _img,
CvHaarClassifierCascade* cascade,
CvMemStorage* storage, double scale_factor,
int min_neighbors, int flags, CvSize min_size )
{
int split_stage = 2;
CvMat stub, *img = (CvMat*)_img;
CvMat *temp = 0, *sum = 0, *tilted = 0, *sqsum = 0, *norm_img = 0, *sumcanny = 0, *img_small = 0;
CvSeq* seq = 0;
CvSeq* seq2 = 0;
CvSeq* idx_seq = 0;
CvSeq* result_seq = 0;
CvMemStorage* temp_storage = 0;
CvAvgComp* comps = 0;
int i;
#ifdef _OPENMP
CvSeq* seq_thread[CV_MAX_THREADS] = {0};
int max_threads = 0;
#endif
CV_FUNCNAME( "cvHaarDetectObjects" );
__BEGIN__;
double factor;
int npass = 2, coi;
int do_canny_pruning = flags & CV_HAAR_DO_CANNY_PRUNING;
if( !CV_IS_HAAR_CLASSIFIER(cascade) )
CV_ERROR( !cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier cascade" );
if( !storage )
CV_ERROR( CV_StsNullPtr, "Null storage pointer" );
CV_CALL( img = cvGetMat( img, &stub, &coi ));
if( coi )
CV_ERROR( CV_BadCOI, "COI is not supported" );
if( CV_MAT_DEPTH(img->type) != CV_8U )
CV_ERROR( CV_StsUnsupportedFormat, "Only 8-bit images are supported" );
CV_CALL( temp = cvCreateMat( img->rows, img->cols, CV_8UC1 ));
CV_CALL( sum = cvCreateMat( img->rows + 1, img->cols + 1, CV_32SC1 ));
CV_CALL( sqsum = cvCreateMat( img->rows + 1, img->cols + 1, CV_64FC1 ));
CV_CALL( temp_storage = cvCreateChildMemStorage( storage ));
#ifdef _OPENMP
max_threads = cvGetNumThreads();
for( i = 0; i < max_threads; i++ )
{
CvMemStorage* temp_storage_thread;
CV_CALL( temp_storage_thread = cvCreateMemStorage(0));
CV_CALL( seq_thread[i] = cvCreateSeq( 0, sizeof(CvSeq),
sizeof(CvRect), temp_storage_thread ));
}
#endif
if( !cascade->hid_cascade )
CV_CALL( icvCreateHidHaarClassifierCascade(cascade) );
if( cascade->hid_cascade->has_tilted_features )
tilted = cvCreateMat( img->rows + 1, img->cols + 1, CV_32SC1 );
seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvRect), temp_storage );
seq2 = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvAvgComp), temp_storage );
result_seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvAvgComp), storage );
if( min_neighbors == 0 )
seq = result_seq;
if( CV_MAT_CN(img->type) > 1 )
{
cvCvtColor( img, temp, CV_BGR2GRAY );
img = temp;
}
if( flags & CV_HAAR_SCALE_IMAGE )
{
CvSize win_size0 = cascade->orig_window_size;
int use_ipp = cascade->hid_cascade->ipp_stages != 0 &&
icvApplyHaarClassifier_32s32f_C1R_p != 0;
if( use_ipp )
CV_CALL( norm_img = cvCreateMat( img->rows, img->cols, CV_32FC1 ));
CV_CALL( img_small = cvCreateMat( img->rows + 1, img->cols + 1, CV_8UC1 ));
for( factor = 1; ; factor *= scale_factor )
{
int positive = 0;
int x, y;
CvSize win_size = { cvRound(win_size0.width*factor),
cvRound(win_size0.height*factor) };
CvSize sz = { cvRound( img->cols/factor ), cvRound( img->rows/factor ) };
CvSize sz1 = { sz.width - win_size0.width, sz.height - win_size0.height };
CvRect rect1 = { icv_object_win_border, icv_object_win_border,
win_size0.width - icv_object_win_border*2,
win_size0.height - icv_object_win_border*2 };
CvMat img1, sum1, sqsum1, norm1, tilted1, mask1;
CvMat* _tilted = 0;
if( sz1.width <= 0 || sz1.height <= 0 )
break;
if( win_size.width < min_size.width || win_size.height < min_size.height )
continue;
img1 = cvMat( sz.height, sz.width, CV_8UC1, img_small->data.ptr );
sum1 = cvMat( sz.height+1, sz.width+1, CV_32SC1, sum->data.ptr );
sqsum1 = cvMat( sz.height+1, sz.width+1, CV_64FC1, sqsum->data.ptr );
if( tilted )
{
tilted1 = cvMat( sz.height+1, sz.width+1, CV_32SC1, tilted->data.ptr );
_tilted = &tilted1;
}
norm1 = cvMat( sz1.height, sz1.width, CV_32FC1, norm_img ? norm_img->data.ptr : 0 );
mask1 = cvMat( sz1.height, sz1.width, CV_8UC1, temp->data.ptr );
cvResize( img, &img1, CV_INTER_LINEAR );
cvIntegral( &img1, &sum1, &sqsum1, _tilted );
if( use_ipp && icvRectStdDev_32s32f_C1R_p( sum1.data.i, sum1.step,
sqsum1.data.db, sqsum1.step, norm1.data.fl, norm1.step, sz1, rect1 ) < 0 )
use_ipp = 0;
if( use_ipp )
{
positive = mask1.cols*mask1.rows;
cvSet( &mask1, cvScalarAll(255) );
for( i = 0; i < cascade->count; i++ )
{
if( icvApplyHaarClassifier_32s32f_C1R_p(sum1.data.i, sum1.step,
norm1.data.fl, norm1.step, mask1.data.ptr, mask1.step,
sz1, &positive, cascade->hid_cascade->stage_classifier[i].threshold,
cascade->hid_cascade->ipp_stages[i]) < 0 )
{
use_ipp = 0;
break;
}
if( positive <= 0 )
break;
}
}
if( !use_ipp )
{
cvSetImagesForHaarClassifierCascade( cascade, &sum1, &sqsum1, 0, 1. );
for( y = 0, positive = 0; y < sz1.height; y++ )
for( x = 0; x < sz1.width; x++ )
{
mask1.data.ptr[mask1.step*y + x] =
cvRunHaarClassifierCascade( cascade, cvPoint(x,y), 0 ) > 0;
positive += mask1.data.ptr[mask1.step*y + x];
}
}
if( positive > 0 )
{
for( y = 0; y < sz1.height; y++ )
for( x = 0; x < sz1.width; x++ )
if( mask1.data.ptr[mask1.step*y + x] != 0 )
{
CvRect obj_rect = { cvRound(y*factor), cvRound(x*factor),
win_size.width, win_size.height };
cvSeqPush( seq, &obj_rect );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -