Update to 2.0.0 tree from current Fremantle build
[opencv] / apps / haartraining / performance.cpp
diff --git a/apps/haartraining/performance.cpp b/apps/haartraining/performance.cpp
new file mode 100644 (file)
index 0000000..2ccea9b
--- /dev/null
@@ -0,0 +1,375 @@
+/*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;
+}
+