Merge pull request #2887 from ilya-lavrenov:ipp_morph_fix
[platform/upstream/opencv.git] / 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 "opencv2/core.hpp"
48
49 #include "cv.h"
50 #include "highgui.h"
51
52 #include <cstdio>
53 #include <cmath>
54 #include <ctime>
55
56 #ifdef _WIN32
57 /* use clock() function insted of time() */
58 #define time( arg ) (((double) clock()) / CLOCKS_PER_SEC)
59 #endif /* _WIN32 */
60
61 #ifndef PATH_MAX
62 #define PATH_MAX 512
63 #endif /* PATH_MAX */
64
65 typedef struct HidCascade
66 {
67     int size;
68     int count;
69 } HidCascade;
70
71 typedef struct ObjectPos
72 {
73     float x;
74     float y;
75     float width;
76     int found;    /* for reference */
77     int neghbors;
78 } ObjectPos;
79
80 int main( int argc, char* argv[] )
81 {
82     int i, j;
83     char* classifierdir = NULL;
84     //char* samplesdir    = NULL;
85
86     int saveDetected = 1;
87     double scale_factor = 1.2;
88     float maxSizeDiff = 1.5F;
89     float maxPosDiff  = 0.3F;
90
91     /* number of stages. if <=0 all stages are used */
92     int nos = -1, nos0;
93
94     int width  = 24;
95     int height = 24;
96
97     int rocsize;
98
99     FILE* info;
100     char* infoname;
101     char fullname[PATH_MAX];
102     char detfilename[PATH_MAX];
103     char* filename;
104     char detname[] = "det-";
105
106     CvHaarClassifierCascade* cascade;
107     CvMemStorage* storage;
108     CvSeq* objects;
109
110     double totaltime;
111
112     infoname = (char*)"";
113     rocsize = 40;
114     if( argc == 1 )
115     {
116         printf( "Usage: %s\n  -data <classifier_directory_name>\n"
117                 "  -info <collection_file_name>\n"
118                 "  [-maxSizeDiff <max_size_difference = %f>]\n"
119                 "  [-maxPosDiff <max_position_difference = %f>]\n"
120                 "  [-sf <scale_factor = %f>]\n"
121                 "  [-ni]\n"
122                 "  [-nos <number_of_stages = %d>]\n"
123                 "  [-rs <roc_size = %d>]\n"
124                 "  [-w <sample_width = %d>]\n"
125                 "  [-h <sample_height = %d>]\n",
126                 argv[0], maxSizeDiff, maxPosDiff, scale_factor, nos, rocsize,
127                 width, height );
128
129         return 0;
130     }
131
132     for( i = 1; i < argc; i++ )
133     {
134         if( !strcmp( argv[i], "-data" ) )
135         {
136             classifierdir = argv[++i];
137         }
138         else if( !strcmp( argv[i], "-info" ) )
139         {
140             infoname = argv[++i];
141         }
142         else if( !strcmp( argv[i], "-maxSizeDiff" ) )
143         {
144             maxSizeDiff = (float) atof( argv[++i] );
145         }
146         else if( !strcmp( argv[i], "-maxPosDiff" ) )
147         {
148             maxPosDiff = (float) atof( argv[++i] );
149         }
150         else if( !strcmp( argv[i], "-sf" ) )
151         {
152             scale_factor = atof( argv[++i] );
153         }
154         else if( !strcmp( argv[i], "-ni" ) )
155         {
156             saveDetected = 0;
157         }
158         else if( !strcmp( argv[i], "-nos" ) )
159         {
160             nos = atoi( argv[++i] );
161         }
162         else if( !strcmp( argv[i], "-rs" ) )
163         {
164             rocsize = atoi( argv[++i] );
165         }
166         else if( !strcmp( argv[i], "-w" ) )
167         {
168             width = atoi( argv[++i] );
169         }
170         else if( !strcmp( argv[i], "-h" ) )
171         {
172             height = atoi( argv[++i] );
173         }
174     }
175
176     cascade = cvLoadHaarClassifierCascade( classifierdir, cvSize( width, height ) );
177     if( cascade == NULL )
178     {
179         printf( "Unable to load classifier from %s\n", classifierdir );
180
181         return 1;
182     }
183
184     int* numclassifiers = new int[cascade->count];
185     numclassifiers[0] = cascade->stage_classifier[0].count;
186     for( i = 1; i < cascade->count; i++ )
187     {
188         numclassifiers[i] = numclassifiers[i-1] + cascade->stage_classifier[i].count;
189     }
190
191     storage = cvCreateMemStorage();
192
193     nos0 = cascade->count;
194     if( nos <= 0 )
195         nos = nos0;
196
197     strcpy( fullname, infoname );
198     filename = strrchr( fullname, '\\' );
199     if( filename == NULL )
200     {
201         filename = strrchr( fullname, '/' );
202     }
203     if( filename == NULL )
204     {
205         filename = fullname;
206     }
207     else
208     {
209         filename++;
210     }
211
212     info = fopen( infoname, "r" );
213     totaltime = 0.0;
214     if( info != NULL )
215     {
216         int x, y;
217         IplImage* img;
218         int hits, missed, falseAlarms;
219         int totalHits, totalMissed, totalFalseAlarms;
220         int found;
221         float distance;
222
223         int refcount;
224         ObjectPos* ref;
225         int detcount;
226         ObjectPos* det;
227         int error=0;
228
229         int* pos;
230         int* neg;
231
232         pos = (int*) cvAlloc( rocsize * sizeof( *pos ) );
233         neg = (int*) cvAlloc( rocsize * sizeof( *neg ) );
234         for( i = 0; i < rocsize; i++ ) { pos[i] = neg[i] = 0; }
235
236         printf( "+================================+======+======+======+\n" );
237         printf( "|            File Name           | Hits |Missed| False|\n" );
238         printf( "+================================+======+======+======+\n" );
239
240         totalHits = totalMissed = totalFalseAlarms = 0;
241         while( !feof( info ) )
242         {
243             if( fscanf( info, "%s %d", filename, &refcount ) != 2 || refcount <= 0 ) break;
244
245             img = cvLoadImage( fullname );
246             if( !img ) continue;
247
248             ref = (ObjectPos*) cvAlloc( refcount * sizeof( *ref ) );
249             for( i = 0; i < refcount; i++ )
250             {
251                 int w, h;
252                 error = (fscanf( info, "%d %d %d %d", &x, &y, &w, &h ) != 4);
253                 if( error ) break;
254                 ref[i].x = 0.5F * w  + x;
255                 ref[i].y = 0.5F * h + y;
256                 ref[i].width = sqrtf( 0.5F * (w * w + h * h) );
257                 ref[i].found = 0;
258                 ref[i].neghbors = 0;
259             }
260             if( !error )
261             {
262                 cvClearMemStorage( storage );
263
264                 cascade->count = nos;
265                 totaltime -= time( 0 );
266                 objects = cvHaarDetectObjects( img, cascade, storage, scale_factor, 1 );
267                 totaltime += time( 0 );
268                 cascade->count = nos0;
269
270                 detcount = ( objects ? objects->total : 0);
271                 det = (detcount > 0) ?
272                     ( (ObjectPos*)cvAlloc( detcount * sizeof( *det )) ) : NULL;
273                 hits = missed = falseAlarms = 0;
274                 for( i = 0; i < detcount; i++ )
275                 {
276                     CvAvgComp r = *((CvAvgComp*) cvGetSeqElem( objects, i ));
277                     det[i].x = 0.5F * r.rect.width  + r.rect.x;
278                     det[i].y = 0.5F * r.rect.height + r.rect.y;
279                     det[i].width = sqrtf( 0.5F * (r.rect.width * r.rect.width +
280                                                   r.rect.height * r.rect.height) );
281                     det[i].neghbors = r.neighbors;
282
283                     if( saveDetected )
284                     {
285                         cvRectangle( img, cvPoint( r.rect.x, r.rect.y ),
286                             cvPoint( r.rect.x + r.rect.width, r.rect.y + r.rect.height ),
287                             CV_RGB( 255, 0, 0 ), 3 );
288                     }
289
290                     found = 0;
291                     for( j = 0; j < refcount; j++ )
292                     {
293                         distance = sqrtf( (det[i].x - ref[j].x) * (det[i].x - ref[j].x) +
294                                           (det[i].y - ref[j].y) * (det[i].y - ref[j].y) );
295                         if( (distance < ref[j].width * maxPosDiff) &&
296                             (det[i].width > ref[j].width / maxSizeDiff) &&
297                             (det[i].width < ref[j].width * maxSizeDiff) )
298                         {
299                             ref[j].found = 1;
300                             ref[j].neghbors = MAX( ref[j].neghbors, det[i].neghbors );
301                             found = 1;
302                         }
303                     }
304                     if( !found )
305                     {
306                         falseAlarms++;
307                         neg[MIN(det[i].neghbors, rocsize - 1)]++;
308                     }
309                 }
310                 for( j = 0; j < refcount; j++ )
311                 {
312                     if( ref[j].found )
313                     {
314                         hits++;
315                         pos[MIN(ref[j].neghbors, rocsize - 1)]++;
316                     }
317                     else
318                     {
319                         missed++;
320                     }
321                 }
322
323                 totalHits += hits;
324                 totalMissed += missed;
325                 totalFalseAlarms += falseAlarms;
326                 printf( "|%32.32s|%6d|%6d|%6d|\n", filename, hits, missed, falseAlarms );
327                 printf( "+--------------------------------+------+------+------+\n" );
328                 fflush( stdout );
329
330                 if( saveDetected )
331                 {
332                     strcpy( detfilename, detname );
333                     strcat( detfilename, filename );
334                     strcpy( filename, detfilename );
335                     cvvSaveImage( fullname, img );
336                 }
337
338                 if( det ) { cvFree( &det ); det = NULL; }
339             } /* if( !error ) */
340
341             cvReleaseImage( &img );
342             cvFree( &ref );
343         }
344         fclose( info );
345
346         printf( "|%32.32s|%6d|%6d|%6d|\n", "Total",
347                 totalHits, totalMissed, totalFalseAlarms );
348         printf( "+================================+======+======+======+\n" );
349         printf( "Number of stages: %d\n", nos );
350         printf( "Number of weak classifiers: %d\n", numclassifiers[nos - 1] );
351         printf( "Total time: %f\n", totaltime );
352
353         /* print ROC to stdout */
354         for( i = rocsize - 1; i > 0; i-- )
355         {
356             pos[i-1] += pos[i];
357             neg[i-1] += neg[i];
358         }
359         fprintf( stderr, "%d\n", nos );
360         for( i = 0; i < rocsize; i++ )
361         {
362             fprintf( stderr, "\t%d\t%d\t%f\t%f\n", pos[i], neg[i],
363                 ((float)pos[i]) / (totalHits + totalMissed),
364                 ((float)neg[i]) / (totalHits + totalMissed) );
365         }
366
367         cvFree( &pos );
368         cvFree( &neg );
369     }
370
371     delete[] numclassifiers;
372
373     cvReleaseHaarClassifierCascade( &cascade );
374     cvReleaseMemStorage( &storage );
375
376     return 0;
377 }