Update to 2.0.0 tree from current Fremantle build
[opencv] / apps / haartraining / performance.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 /*
43  * performance.cpp
44  *
45  * Measure performance of classifier
46  */
47 #include <cv.h>
48 #include <highgui.h>
49
50 #include <cstdio>
51 #include <cmath>
52 #include <ctime>
53
54 #ifdef _WIN32
55 /* use clock() function insted of time() */
56 #define time( arg ) (((double) clock()) / CLOCKS_PER_SEC)
57 #endif /* _WIN32 */
58
59 #ifndef PATH_MAX
60 #define PATH_MAX 512
61 #endif /* PATH_MAX */
62
63 typedef struct HidCascade
64 {
65     int size;
66     int count;
67 } HidCascade;
68
69 typedef struct ObjectPos
70 {
71     float x;
72     float y;
73     float width;
74     int found;    /* for reference */
75     int neghbors;
76 } ObjectPos;
77
78 int main( int argc, char* argv[] )
79 {
80     int i, j;
81     char* classifierdir = NULL;
82     //char* samplesdir    = NULL;
83
84     int saveDetected = 1;
85     double scale_factor = 1.2;
86     float maxSizeDiff = 1.5F;
87     float maxPosDiff  = 0.3F;
88
89     /* number of stages. if <=0 all stages are used */
90     int nos = -1, nos0;
91
92     int width  = 24;
93     int height = 24;
94
95     int rocsize;
96
97     FILE* info;
98     char* infoname;
99     char fullname[PATH_MAX];
100     char detfilename[PATH_MAX];
101     char* filename;
102     char detname[] = "det-";
103
104     CvHaarClassifierCascade* cascade;
105     CvMemStorage* storage;
106     CvSeq* objects;
107
108     double totaltime;
109
110     infoname = (char*)"";
111     rocsize = 40;
112     if( argc == 1 )
113     {
114         printf( "Usage: %s\n  -data <classifier_directory_name>\n"
115                 "  -info <collection_file_name>\n"
116                 "  [-maxSizeDiff <max_size_difference = %f>]\n"
117                 "  [-maxPosDiff <max_position_difference = %f>]\n"
118                 "  [-sf <scale_factor = %f>]\n"
119                 "  [-ni]\n"
120                 "  [-nos <number_of_stages = %d>]\n"
121                 "  [-rs <roc_size = %d>]\n"
122                 "  [-w <sample_width = %d>]\n"
123                 "  [-h <sample_height = %d>]\n",
124                 argv[0], maxSizeDiff, maxPosDiff, scale_factor, nos, rocsize,
125                 width, height );
126
127         return 0;
128     }
129
130     for( i = 1; i < argc; i++ )
131     {
132         if( !strcmp( argv[i], "-data" ) )
133         {
134             classifierdir = argv[++i];
135         }
136         else if( !strcmp( argv[i], "-info" ) )
137         {
138             infoname = argv[++i];
139         }
140         else if( !strcmp( argv[i], "-maxSizeDiff" ) )
141         {
142             maxSizeDiff = (float) atof( argv[++i] );
143         }
144         else if( !strcmp( argv[i], "-maxPosDiff" ) )
145         {
146             maxPosDiff = (float) atof( argv[++i] );
147         }
148         else if( !strcmp( argv[i], "-sf" ) )
149         {
150             scale_factor = atof( argv[++i] );
151         }
152         else if( !strcmp( argv[i], "-ni" ) )
153         {
154             saveDetected = 0;
155         }
156         else if( !strcmp( argv[i], "-nos" ) )
157         {
158             nos = atoi( argv[++i] );
159         }
160         else if( !strcmp( argv[i], "-rs" ) )
161         {
162             rocsize = atoi( argv[++i] );
163         }
164         else if( !strcmp( argv[i], "-w" ) )
165         {
166             width = atoi( argv[++i] );
167         }
168         else if( !strcmp( argv[i], "-h" ) )
169         {
170             height = atoi( argv[++i] );
171         }
172     }
173
174     cascade = cvLoadHaarClassifierCascade( classifierdir, cvSize( width, height ) );
175     if( cascade == NULL )
176     {
177         printf( "Unable to load classifier from %s\n", classifierdir );
178
179         return 1;
180     }
181
182     int* numclassifiers = new int[cascade->count];
183     numclassifiers[0] = cascade->stage_classifier[0].count;
184     for( i = 1; i < cascade->count; i++ )
185     {
186         numclassifiers[i] = numclassifiers[i-1] + cascade->stage_classifier[i].count;
187     }
188
189     storage = cvCreateMemStorage();
190
191     nos0 = cascade->count;
192     if( nos <= 0 )
193         nos = nos0;
194
195     strcpy( fullname, infoname );
196     filename = strrchr( fullname, '\\' );
197     if( filename == NULL )
198     {
199         filename = strrchr( fullname, '/' );
200     }
201     if( filename == NULL )
202     {
203         filename = fullname;
204     }
205     else
206     {
207         filename++;
208     }
209
210     info = fopen( infoname, "r" );
211     totaltime = 0.0;
212     if( info != NULL )
213     {
214         int x, y, width, height;
215         IplImage* img;
216         int hits, missed, falseAlarms;
217         int totalHits, totalMissed, totalFalseAlarms;
218         int found;
219         float distance;
220
221         int refcount;
222         ObjectPos* ref;
223         int detcount;
224         ObjectPos* det;
225         int error=0;
226
227         int* pos;
228         int* neg;
229
230         pos = (int*) cvAlloc( rocsize * sizeof( *pos ) );
231         neg = (int*) cvAlloc( rocsize * sizeof( *neg ) );
232         for( i = 0; i < rocsize; i++ ) { pos[i] = neg[i] = 0; }
233
234         printf( "+================================+======+======+======+\n" );
235         printf( "|            File Name           | Hits |Missed| False|\n" );
236         printf( "+================================+======+======+======+\n" );
237
238         totalHits = totalMissed = totalFalseAlarms = 0;
239         while( !feof( info ) )
240         {
241             if( fscanf( info, "%s %d", filename, &refcount ) != 2 || refcount <= 0 ) break;
242
243             img = cvLoadImage( fullname );
244             if( !img ) continue;
245
246             ref = (ObjectPos*) cvAlloc( refcount * sizeof( *ref ) );
247             for( i = 0; i < refcount; i++ )
248             {
249                 error = (fscanf( info, "%d %d %d %d", &x, &y, &width, &height ) != 4);
250                 if( error ) break;
251                 ref[i].x = 0.5F * width  + x;
252                 ref[i].y = 0.5F * height + y;
253                 ref[i].width = sqrtf( 0.5F * (width * width + height * height) );
254                 ref[i].found = 0;
255                 ref[i].neghbors = 0;
256             }
257             if( !error )
258             {
259                 cvClearMemStorage( storage );
260
261                 cascade->count = nos;
262                 totaltime -= time( 0 );
263                 objects = cvHaarDetectObjects( img, cascade, storage, scale_factor, 1 );
264                 totaltime += time( 0 );
265                 cascade->count = nos0;
266
267                 detcount = ( objects ? objects->total : 0);
268                 det = (detcount > 0) ?
269                     ( (ObjectPos*)cvAlloc( detcount * sizeof( *det )) ) : NULL;
270                 hits = missed = falseAlarms = 0;
271                 for( i = 0; i < detcount; i++ )
272                 {
273                     CvAvgComp r = *((CvAvgComp*) cvGetSeqElem( objects, i ));
274                     det[i].x = 0.5F * r.rect.width  + r.rect.x;
275                     det[i].y = 0.5F * r.rect.height + r.rect.y;
276                     det[i].width = sqrtf( 0.5F * (r.rect.width * r.rect.width +
277                                                   r.rect.height * r.rect.height) );
278                     det[i].neghbors = r.neighbors;
279
280                     if( saveDetected )
281                     {
282                         cvRectangle( img, cvPoint( r.rect.x, r.rect.y ),
283                             cvPoint( r.rect.x + r.rect.width, r.rect.y + r.rect.height ),
284                             CV_RGB( 255, 0, 0 ), 3 );
285                     }
286
287                     found = 0;
288                     for( j = 0; j < refcount; j++ )
289                     {
290                         distance = sqrtf( (det[i].x - ref[j].x) * (det[i].x - ref[j].x) +
291                                           (det[i].y - ref[j].y) * (det[i].y - ref[j].y) );
292                         if( (distance < ref[j].width * maxPosDiff) &&
293                             (det[i].width > ref[j].width / maxSizeDiff) &&
294                             (det[i].width < ref[j].width * maxSizeDiff) )
295                         {
296                             ref[j].found = 1;
297                             ref[j].neghbors = MAX( ref[j].neghbors, det[i].neghbors );
298                             found = 1;
299                         }
300                     }
301                     if( !found )
302                     {
303                         falseAlarms++;
304                         neg[MIN(det[i].neghbors, rocsize - 1)]++;
305                     }
306                 }
307                 for( j = 0; j < refcount; j++ )
308                 {
309                     if( ref[j].found )
310                     {
311                         hits++;
312                         pos[MIN(ref[j].neghbors, rocsize - 1)]++;
313                     }
314                     else
315                     {
316                         missed++;
317                     }
318                 }
319
320                 totalHits += hits;
321                 totalMissed += missed;
322                 totalFalseAlarms += falseAlarms;
323                 printf( "|%32.32s|%6d|%6d|%6d|\n", filename, hits, missed, falseAlarms );
324                 printf( "+--------------------------------+------+------+------+\n" );
325                 fflush( stdout );
326
327                 if( saveDetected )
328                 {
329                     strcpy( detfilename, detname );
330                     strcat( detfilename, filename );
331                     strcpy( filename, detfilename );
332                     cvvSaveImage( fullname, img );
333                 }
334
335                 if( det ) { cvFree( &det ); det = NULL; }
336             } /* if( !error ) */
337
338             cvReleaseImage( &img );
339             cvFree( &ref );
340         }
341         fclose( info );
342
343         printf( "|%32.32s|%6d|%6d|%6d|\n", "Total",
344                 totalHits, totalMissed, totalFalseAlarms );
345         printf( "+================================+======+======+======+\n" );
346         printf( "Number of stages: %d\n", nos );
347         printf( "Number of weak classifiers: %d\n", numclassifiers[nos - 1] );
348         printf( "Total time: %f\n", totaltime );
349
350         /* print ROC to stdout */
351         for( i = rocsize - 1; i > 0; i-- )
352         {
353             pos[i-1] += pos[i];
354             neg[i-1] += neg[i];
355         }
356         fprintf( stderr, "%d\n", nos );
357         for( i = 0; i < rocsize; i++ )
358         {
359             fprintf( stderr, "\t%d\t%d\t%f\t%f\n", pos[i], neg[i],
360                 ((float)pos[i]) / (totalHits + totalMissed),
361                 ((float)neg[i]) / (totalHits + totalMissed) );
362         }
363
364         cvFree( &pos );
365         cvFree( &neg );
366     }
367
368     delete[] numclassifiers;
369
370     cvReleaseHaarClassifierCascade( &cascade );
371     cvReleaseMemStorage( &storage );
372
373     return 0;
374 }
375