📄 cvhaar.cpp
字号:
if( sscanf( stage, "%d%d%n", &parent, &next, &dl ) != 2 )
{
parent = i - 1;
next = -1;
}
stage += dl;
cascade->stage_classifier[i].parent = parent;
cascade->stage_classifier[i].next = next;
cascade->stage_classifier[i].child = -1;
if( parent != -1 && cascade->stage_classifier[parent].child == -1 )
{
cascade->stage_classifier[parent].child = i;
}
}
return cascade;
}
#ifndef _MAX_PATH
#define _MAX_PATH 1024
#endif
CV_IMPL CvHaarClassifierCascade*
cvLoadHaarClassifierCascade( const char* directory, CvSize orig_window_size )
{
const char** input_cascade = 0;
CvHaarClassifierCascade *cascade = 0;
CV_FUNCNAME( "cvLoadHaarClassifierCascade" );
__BEGIN__;
int i, n;
const char* slash;
char name[_MAX_PATH];
int size = 0;
char* ptr = 0;
if( !directory )
CV_ERROR( CV_StsNullPtr, "Null path is passed" );
n = (int)strlen(directory)-1;
slash = directory[n] == '\\' || directory[n] == '/' ? "" : "/";
/* try to read the classifier from directory */
for( n = 0; ; n++ )
{
sprintf( name, "%s%s%d/AdaBoostCARTHaarClassifier.txt", directory, slash, n );
FILE* f = fopen( name, "rb" );
if( !f )
break;
fseek( f, 0, SEEK_END );
size += ftell( f ) + 1;
fclose(f);
}
if( n == 0 && slash[0] )
{
CV_CALL( cascade = (CvHaarClassifierCascade*)cvLoad( directory ));
EXIT;
}
else if( n == 0 )
CV_ERROR( CV_StsBadArg, "Invalid path" );
size += (n+1)*sizeof(char*);
CV_CALL( input_cascade = (const char**)cvAlloc( size ));
ptr = (char*)(input_cascade + n + 1);
for( i = 0; i < n; i++ )
{
sprintf( name, "%s/%d/AdaBoostCARTHaarClassifier.txt", directory, i );
FILE* f = fopen( name, "rb" );
if( !f )
CV_ERROR( CV_StsError, "" );
fseek( f, 0, SEEK_END );
size = ftell( f );
fseek( f, 0, SEEK_SET );
fread( ptr, 1, size, f );
fclose(f);
input_cascade[i] = ptr;
ptr += size;
*ptr++ = '\0';
}
input_cascade[n] = 0;
cascade = icvLoadCascadeCART( input_cascade, n, orig_window_size );
__END__;
if( input_cascade )
cvFree( &input_cascade );
if( cvGetErrStatus() < 0 )
cvReleaseHaarClassifierCascade( &cascade );
return cascade;
}
CV_IMPL void
cvReleaseHaarClassifierCascade( CvHaarClassifierCascade** _cascade )
{
if( _cascade && *_cascade )
{
int i, j;
CvHaarClassifierCascade* cascade = *_cascade;
for( i = 0; i < cascade->count; i++ )
{
for( j = 0; j < cascade->stage_classifier[i].count; j++ )
cvFree( &cascade->stage_classifier[i].classifier[j].haar_feature );
cvFree( &cascade->stage_classifier[i].classifier );
}
icvReleaseHidHaarClassifierCascade( &cascade->hid_cascade );
cvFree( _cascade );
}
}
/****************************************************************************************\
* Persistence functions *
\****************************************************************************************/
/* field names */
#define ICV_HAAR_SIZE_NAME "size"
#define ICV_HAAR_STAGES_NAME "stages"
#define ICV_HAAR_TREES_NAME "trees"
#define ICV_HAAR_FEATURE_NAME "feature"
#define ICV_HAAR_RECTS_NAME "rects"
#define ICV_HAAR_TILTED_NAME "tilted"
#define ICV_HAAR_THRESHOLD_NAME "threshold"
#define ICV_HAAR_LEFT_NODE_NAME "left_node"
#define ICV_HAAR_LEFT_VAL_NAME "left_val"
#define ICV_HAAR_RIGHT_NODE_NAME "right_node"
#define ICV_HAAR_RIGHT_VAL_NAME "right_val"
#define ICV_HAAR_STAGE_THRESHOLD_NAME "stage_threshold"
#define ICV_HAAR_PARENT_NAME "parent"
#define ICV_HAAR_NEXT_NAME "next"
static int
icvIsHaarClassifier( const void* struct_ptr )
{
return CV_IS_HAAR_CLASSIFIER( struct_ptr );
}
static void*
icvReadHaarClassifier( CvFileStorage* fs, CvFileNode* node )
{
CvHaarClassifierCascade* cascade = NULL;
CV_FUNCNAME( "cvReadHaarClassifier" );
__BEGIN__;
char buf[256];
CvFileNode* seq_fn = NULL; /* sequence */
CvFileNode* fn = NULL;
CvFileNode* stages_fn = NULL;
CvSeqReader stages_reader;
int n;
int i, j, k, l;
int parent, next;
CV_CALL( stages_fn = cvGetFileNodeByName( fs, node, ICV_HAAR_STAGES_NAME ) );
if( !stages_fn || !CV_NODE_IS_SEQ( stages_fn->tag) )
CV_ERROR( CV_StsError, "Invalid stages node" );
n = stages_fn->data.seq->total;
CV_CALL( cascade = icvCreateHaarClassifierCascade(n) );
/* read size */
CV_CALL( seq_fn = cvGetFileNodeByName( fs, node, ICV_HAAR_SIZE_NAME ) );
if( !seq_fn || !CV_NODE_IS_SEQ( seq_fn->tag ) || seq_fn->data.seq->total != 2 )
CV_ERROR( CV_StsError, "size node is not a valid sequence." );
CV_CALL( fn = (CvFileNode*) cvGetSeqElem( seq_fn->data.seq, 0 ) );
if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= 0 )
CV_ERROR( CV_StsError, "Invalid size node: width must be positive integer" );
cascade->orig_window_size.width = fn->data.i;
CV_CALL( fn = (CvFileNode*) cvGetSeqElem( seq_fn->data.seq, 1 ) );
if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= 0 )
CV_ERROR( CV_StsError, "Invalid size node: height must be positive integer" );
cascade->orig_window_size.height = fn->data.i;
CV_CALL( cvStartReadSeq( stages_fn->data.seq, &stages_reader ) );
for( i = 0; i < n; ++i )
{
CvFileNode* stage_fn;
CvFileNode* trees_fn;
CvSeqReader trees_reader;
stage_fn = (CvFileNode*) stages_reader.ptr;
if( !CV_NODE_IS_MAP( stage_fn->tag ) )
{
sprintf( buf, "Invalid stage %d", i );
CV_ERROR( CV_StsError, buf );
}
CV_CALL( trees_fn = cvGetFileNodeByName( fs, stage_fn, ICV_HAAR_TREES_NAME ) );
if( !trees_fn || !CV_NODE_IS_SEQ( trees_fn->tag )
|| trees_fn->data.seq->total <= 0 )
{
sprintf( buf, "Trees node is not a valid sequence. (stage %d)", i );
CV_ERROR( CV_StsError, buf );
}
CV_CALL( cascade->stage_classifier[i].classifier =
(CvHaarClassifier*) cvAlloc( trees_fn->data.seq->total
* sizeof( cascade->stage_classifier[i].classifier[0] ) ) );
for( j = 0; j < trees_fn->data.seq->total; ++j )
{
cascade->stage_classifier[i].classifier[j].haar_feature = NULL;
}
cascade->stage_classifier[i].count = trees_fn->data.seq->total;
CV_CALL( cvStartReadSeq( trees_fn->data.seq, &trees_reader ) );
for( j = 0; j < trees_fn->data.seq->total; ++j )
{
CvFileNode* tree_fn;
CvSeqReader tree_reader;
CvHaarClassifier* classifier;
int last_idx;
classifier = &cascade->stage_classifier[i].classifier[j];
tree_fn = (CvFileNode*) trees_reader.ptr;
if( !CV_NODE_IS_SEQ( tree_fn->tag ) || tree_fn->data.seq->total <= 0 )
{
sprintf( buf, "Tree node is not a valid sequence."
" (stage %d, tree %d)", i, j );
CV_ERROR( CV_StsError, buf );
}
classifier->count = tree_fn->data.seq->total;
CV_CALL( classifier->haar_feature = (CvHaarFeature*) cvAlloc(
classifier->count * ( sizeof( *classifier->haar_feature ) +
sizeof( *classifier->threshold ) +
sizeof( *classifier->left ) +
sizeof( *classifier->right ) ) +
(classifier->count + 1) * sizeof( *classifier->alpha ) ) );
classifier->threshold = (float*) (classifier->haar_feature+classifier->count);
classifier->left = (int*) (classifier->threshold + classifier->count);
classifier->right = (int*) (classifier->left + classifier->count);
classifier->alpha = (float*) (classifier->right + classifier->count);
CV_CALL( cvStartReadSeq( tree_fn->data.seq, &tree_reader ) );
for( k = 0, last_idx = 0; k < tree_fn->data.seq->total; ++k )
{
CvFileNode* node_fn;
CvFileNode* feature_fn;
CvFileNode* rects_fn;
CvSeqReader rects_reader;
node_fn = (CvFileNode*) tree_reader.ptr;
if( !CV_NODE_IS_MAP( node_fn->tag ) )
{
sprintf( buf, "Tree node %d is not a valid map. (stage %d, tree %d)",
k, i, j );
CV_ERROR( CV_StsError, buf );
}
CV_CALL( feature_fn = cvGetFileNodeByName( fs, node_fn,
ICV_HAAR_FEATURE_NAME ) );
if( !feature_fn || !CV_NODE_IS_MAP( feature_fn->tag ) )
{
sprintf( buf, "Feature node is not a valid map. "
"(stage %d, tree %d, node %d)", i, j, k );
CV_ERROR( CV_StsError, buf );
}
CV_CALL( rects_fn = cvGetFileNodeByName( fs, feature_fn,
ICV_HAAR_RECTS_NAME ) );
if( !rects_fn || !CV_NODE_IS_SEQ( rects_fn->tag )
|| rects_fn->data.seq->total < 1
|| rects_fn->data.seq->total > CV_HAAR_FEATURE_MAX )
{
sprintf( buf, "Rects node is not a valid sequence. "
"(stage %d, tree %d, node %d)", i, j, k );
CV_ERROR( CV_StsError, buf );
}
CV_CALL( cvStartReadSeq( rects_fn->data.seq, &rects_reader ) );
for( l = 0; l < rects_fn->data.seq->total; ++l )
{
CvFileNode* rect_fn;
CvRect r;
rect_fn = (CvFileNode*) rects_reader.ptr;
if( !CV_NODE_IS_SEQ( rect_fn->tag ) || rect_fn->data.seq->total != 5 )
{
sprintf( buf, "Rect %d is not a valid sequence. "
"(stage %d, tree %d, node %d)", l, i, j, k );
CV_ERROR( CV_StsError, buf );
}
fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 0 );
if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i < 0 )
{
sprintf( buf, "x coordinate must be non-negative integer. "
"(stage %d, tree %d, node %d, rect %d)", i, j, k, l );
CV_ERROR( CV_StsError, buf );
}
r.x = fn->data.i;
fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 1 );
if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i < 0 )
{
sprintf( buf, "y coordinate must be non-negative integer. "
"(stage %d, tree %d, node %d, rect %d)", i, j, k, l );
CV_ERROR( CV_StsError, buf );
}
r.y = fn->data.i;
fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 2 );
if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= 0
|| r.x + fn->data.i > cascade->orig_window_size.width )
{
sprintf( buf, "width must be positive integer and "
"(x + width) must not exceed window width. "
"(stage %d, tree %d, node %d, rect %d)", i, j, k, l );
CV_ERROR( CV_StsError, buf );
}
r.width = fn->data.i;
fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 3 );
if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= 0
|| r.y + fn->data.i > cascade->orig_window_size.height )
{
sprintf( buf, "height must be positive integer and "
"(y + height) must not exceed window height. "
"(stage %d, tree %d, node %d, rect %d)", i, j, k, l );
CV_ERROR( CV_StsError, buf );
}
r.height = fn->data.i;
fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 4 );
if( !CV_NODE_IS_REAL( fn->tag ) )
{
sprintf( buf, "weight must be real number. "
"(stage %d, tree %d, node %d, rect %d)", i, j, k, l );
CV_ERROR( CV_StsError, buf );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -