opencv/apps/haartraining/performance.cpp

376 lines
12 KiB
C++
Raw Normal View History

/*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 "cv.h"
#include "highgui.h"
#include <cstdio>
#include <cmath>
#include <ctime>
#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 <classifier_directory_name>\n"
" -info <collection_file_name>\n"
" [-maxSizeDiff <max_size_difference = %f>]\n"
" [-maxPosDiff <max_position_difference = %f>]\n"
" [-sf <scale_factor = %f>]\n"
" [-ni]\n"
" [-nos <number_of_stages = %d>]\n"
" [-rs <roc_size = %d>]\n"
" [-w <sample_width = %d>]\n"
" [-h <sample_height = %d>]\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;
}