/*M/////////////////////////////////////////////////////////////////////////////////////// // // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. // // By downloading, copying, installing or using the software you agree to this license. // If you do not agree to this license, do not download, install, // copy or use the software. // // // Intel License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000, Intel Corporation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // * Redistribution's of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // * Redistribution's in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // * The name of Intel Corporation may not be used to endorse or promote products // derived from this software without specific prior written permission. // // This software is provided by the copyright holders and contributors "as is" and // any express or implied warranties, including, but not limited to, the implied // warranties of merchantability and fitness for a particular purpose are disclaimed. // In no event shall the Intel Corporation or contributors be liable for any direct, // indirect, incidental, special, exemplary, or consequential damages // (including, but not limited to, procurement of substitute goods or services; // loss of use, data, or profits; or business interruption) however caused // and on any theory of liability, whether in contract, strict liability, // or tort (including negligence or otherwise) arising in any way out of // the use of this software, even if advised of the possibility of such damage. // //M*/ /* * performance.cpp * * Measure performance of classifier */ #include "opencv2/core/core.hpp" #include "opencv2/core/internal.hpp" #include "cv.h" #include "highgui.h" #include #include #include #ifdef _WIN32 /* use clock() function insted of time() */ #define time( arg ) (((double) clock()) / CLOCKS_PER_SEC) #endif /* _WIN32 */ #ifndef PATH_MAX #define PATH_MAX 512 #endif /* PATH_MAX */ typedef struct HidCascade { int size; int count; } HidCascade; typedef struct ObjectPos { float x; float y; float width; int found; /* for reference */ int neghbors; } ObjectPos; int main( int argc, char* argv[] ) { int i, j; char* classifierdir = NULL; //char* samplesdir = NULL; int saveDetected = 1; double scale_factor = 1.2; float maxSizeDiff = 1.5F; float maxPosDiff = 0.3F; /* number of stages. if <=0 all stages are used */ int nos = -1, nos0; int width = 24; int height = 24; int rocsize; FILE* info; char* infoname; char fullname[PATH_MAX]; char detfilename[PATH_MAX]; char* filename; char detname[] = "det-"; CvHaarClassifierCascade* cascade; CvMemStorage* storage; CvSeq* objects; double totaltime; infoname = (char*)""; rocsize = 40; if( argc == 1 ) { printf( "Usage: %s\n -data \n" " -info \n" " [-maxSizeDiff ]\n" " [-maxPosDiff ]\n" " [-sf ]\n" " [-ni]\n" " [-nos ]\n" " [-rs ]\n" " [-w ]\n" " [-h ]\n", argv[0], maxSizeDiff, maxPosDiff, scale_factor, nos, rocsize, width, height ); return 0; } for( i = 1; i < argc; i++ ) { if( !strcmp( argv[i], "-data" ) ) { classifierdir = argv[++i]; } else if( !strcmp( argv[i], "-info" ) ) { infoname = argv[++i]; } else if( !strcmp( argv[i], "-maxSizeDiff" ) ) { maxSizeDiff = (float) atof( argv[++i] ); } else if( !strcmp( argv[i], "-maxPosDiff" ) ) { maxPosDiff = (float) atof( argv[++i] ); } else if( !strcmp( argv[i], "-sf" ) ) { scale_factor = atof( argv[++i] ); } else if( !strcmp( argv[i], "-ni" ) ) { saveDetected = 0; } else if( !strcmp( argv[i], "-nos" ) ) { nos = atoi( argv[++i] ); } else if( !strcmp( argv[i], "-rs" ) ) { rocsize = atoi( argv[++i] ); } else if( !strcmp( argv[i], "-w" ) ) { width = atoi( argv[++i] ); } else if( !strcmp( argv[i], "-h" ) ) { height = atoi( argv[++i] ); } } cascade = cvLoadHaarClassifierCascade( classifierdir, cvSize( width, height ) ); if( cascade == NULL ) { printf( "Unable to load classifier from %s\n", classifierdir ); return 1; } int* numclassifiers = new int[cascade->count]; numclassifiers[0] = cascade->stage_classifier[0].count; for( i = 1; i < cascade->count; i++ ) { numclassifiers[i] = numclassifiers[i-1] + cascade->stage_classifier[i].count; } storage = cvCreateMemStorage(); nos0 = cascade->count; if( nos <= 0 ) nos = nos0; strcpy( fullname, infoname ); filename = strrchr( fullname, '\\' ); if( filename == NULL ) { filename = strrchr( fullname, '/' ); } if( filename == NULL ) { filename = fullname; } else { filename++; } info = fopen( infoname, "r" ); totaltime = 0.0; if( info != NULL ) { int x, y, width, height; IplImage* img; int hits, missed, falseAlarms; int totalHits, totalMissed, totalFalseAlarms; int found; float distance; int refcount; ObjectPos* ref; int detcount; ObjectPos* det; int error=0; int* pos; int* neg; pos = (int*) cvAlloc( rocsize * sizeof( *pos ) ); neg = (int*) cvAlloc( rocsize * sizeof( *neg ) ); for( i = 0; i < rocsize; i++ ) { pos[i] = neg[i] = 0; } printf( "+================================+======+======+======+\n" ); printf( "| File Name | Hits |Missed| False|\n" ); printf( "+================================+======+======+======+\n" ); totalHits = totalMissed = totalFalseAlarms = 0; while( !feof( info ) ) { if( fscanf( info, "%s %d", filename, &refcount ) != 2 || refcount <= 0 ) break; img = cvLoadImage( fullname ); if( !img ) continue; ref = (ObjectPos*) cvAlloc( refcount * sizeof( *ref ) ); for( i = 0; i < refcount; i++ ) { error = (fscanf( info, "%d %d %d %d", &x, &y, &width, &height ) != 4); if( error ) break; ref[i].x = 0.5F * width + x; ref[i].y = 0.5F * height + y; ref[i].width = sqrtf( 0.5F * (width * width + height * height) ); ref[i].found = 0; ref[i].neghbors = 0; } if( !error ) { cvClearMemStorage( storage ); cascade->count = nos; totaltime -= time( 0 ); objects = cvHaarDetectObjects( img, cascade, storage, scale_factor, 1 ); totaltime += time( 0 ); cascade->count = nos0; detcount = ( objects ? objects->total : 0); det = (detcount > 0) ? ( (ObjectPos*)cvAlloc( detcount * sizeof( *det )) ) : NULL; hits = missed = falseAlarms = 0; for( i = 0; i < detcount; i++ ) { CvAvgComp r = *((CvAvgComp*) cvGetSeqElem( objects, i )); det[i].x = 0.5F * r.rect.width + r.rect.x; det[i].y = 0.5F * r.rect.height + r.rect.y; det[i].width = sqrtf( 0.5F * (r.rect.width * r.rect.width + r.rect.height * r.rect.height) ); det[i].neghbors = r.neighbors; if( saveDetected ) { cvRectangle( img, cvPoint( r.rect.x, r.rect.y ), cvPoint( r.rect.x + r.rect.width, r.rect.y + r.rect.height ), CV_RGB( 255, 0, 0 ), 3 ); } found = 0; for( j = 0; j < refcount; j++ ) { distance = sqrtf( (det[i].x - ref[j].x) * (det[i].x - ref[j].x) + (det[i].y - ref[j].y) * (det[i].y - ref[j].y) ); if( (distance < ref[j].width * maxPosDiff) && (det[i].width > ref[j].width / maxSizeDiff) && (det[i].width < ref[j].width * maxSizeDiff) ) { ref[j].found = 1; ref[j].neghbors = MAX( ref[j].neghbors, det[i].neghbors ); found = 1; } } if( !found ) { falseAlarms++; neg[MIN(det[i].neghbors, rocsize - 1)]++; } } for( j = 0; j < refcount; j++ ) { if( ref[j].found ) { hits++; pos[MIN(ref[j].neghbors, rocsize - 1)]++; } else { missed++; } } totalHits += hits; totalMissed += missed; totalFalseAlarms += falseAlarms; printf( "|%32.32s|%6d|%6d|%6d|\n", filename, hits, missed, falseAlarms ); printf( "+--------------------------------+------+------+------+\n" ); fflush( stdout ); if( saveDetected ) { strcpy( detfilename, detname ); strcat( detfilename, filename ); strcpy( filename, detfilename ); cvvSaveImage( fullname, img ); } if( det ) { cvFree( &det ); det = NULL; } } /* if( !error ) */ cvReleaseImage( &img ); cvFree( &ref ); } fclose( info ); printf( "|%32.32s|%6d|%6d|%6d|\n", "Total", totalHits, totalMissed, totalFalseAlarms ); printf( "+================================+======+======+======+\n" ); printf( "Number of stages: %d\n", nos ); printf( "Number of weak classifiers: %d\n", numclassifiers[nos - 1] ); printf( "Total time: %f\n", totaltime ); /* print ROC to stdout */ for( i = rocsize - 1; i > 0; i-- ) { pos[i-1] += pos[i]; neg[i-1] += neg[i]; } fprintf( stderr, "%d\n", nos ); for( i = 0; i < rocsize; i++ ) { fprintf( stderr, "\t%d\t%d\t%f\t%f\n", pos[i], neg[i], ((float)pos[i]) / (totalHits + totalMissed), ((float)neg[i]) / (totalHits + totalMissed) ); } cvFree( &pos ); cvFree( &neg ); } delete[] numclassifiers; cvReleaseHaarClassifierCascade( &cascade ); cvReleaseMemStorage( &storage ); return 0; }