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 #include <cstring>
43 #include <ctime>
44 
45 #include <sys/stat.h>
46 #include <sys/types.h>
47 #ifdef _WIN32
48 #include <direct.h>
49 #endif /* _WIN32 */
50 
51 #include "utility.hpp"
52 #include "opencv2/core.hpp"
53 #include "opencv2/core/core_c.h"
54 #include "opencv2/imgcodecs/imgcodecs_c.h"
55 #include "opencv2/imgproc/imgproc_c.h"
56 #include "opencv2/highgui/highgui_c.h"
57 #include "opencv2/calib3d/calib3d_c.h"
58 
59 #ifndef PATH_MAX
60 #define PATH_MAX 512
61 #endif /* PATH_MAX */
62 
63 #define __BEGIN__ __CV_BEGIN__
64 #define __END__  __CV_END__
65 #define EXIT __CV_EXIT__
66 
icvMkDir(const char * filename)67 static int icvMkDir( const char* filename )
68 {
69     char path[PATH_MAX];
70     char* p;
71     int pos;
72 
73 #ifdef _WIN32
74     struct _stat st;
75 #else /* _WIN32 */
76     struct stat st;
77     mode_t mode;
78 
79     mode = 0755;
80 #endif /* _WIN32 */
81 
82     strcpy( path, filename );
83 
84     p = path;
85     for( ; ; )
86     {
87         pos = (int)strcspn( p, "/\\" );
88 
89         if( pos == (int) strlen( p ) ) break;
90         if( pos != 0 )
91         {
92             p[pos] = '\0';
93 
94 #ifdef _WIN32
95             if( p[pos-1] != ':' )
96             {
97                 if( _stat( path, &st ) != 0 )
98                 {
99                     if( _mkdir( path ) != 0 ) return 0;
100                 }
101             }
102 #else /* _WIN32 */
103             if( stat( path, &st ) != 0 )
104             {
105                 if( mkdir( path, mode ) != 0 ) return 0;
106             }
107 #endif /* _WIN32 */
108         }
109 
110         p[pos] = '/';
111 
112         p += pos + 1;
113     }
114 
115     return 1;
116 }
117 
icvWriteVecHeader(FILE * file,int count,int width,int height)118 static void icvWriteVecHeader( FILE* file, int count, int width, int height )
119 {
120     int vecsize;
121     short tmp;
122 
123     /* number of samples */
124     fwrite( &count, sizeof( count ), 1, file );
125     /* vector size */
126     vecsize = width * height;
127     fwrite( &vecsize, sizeof( vecsize ), 1, file );
128     /* min/max values */
129     tmp = 0;
130     fwrite( &tmp, sizeof( tmp ), 1, file );
131     fwrite( &tmp, sizeof( tmp ), 1, file );
132 }
133 
icvWriteVecSample(FILE * file,CvArr * sample)134 static void icvWriteVecSample( FILE* file, CvArr* sample )
135 {
136     CvMat* mat, stub;
137     int r, c;
138     short tmp;
139     uchar chartmp;
140 
141     mat = cvGetMat( sample, &stub );
142     chartmp = 0;
143     fwrite( &chartmp, sizeof( chartmp ), 1, file );
144     for( r = 0; r < mat->rows; r++ )
145     {
146         for( c = 0; c < mat->cols; c++ )
147         {
148             tmp = (short) (CV_MAT_ELEM( *mat, uchar, r, c ));
149             fwrite( &tmp, sizeof( tmp ), 1, file );
150         }
151     }
152 }
153 
154 /* Calculates coefficients of perspective transformation
155  * which maps <quad> into rectangle ((0,0), (w,0), (w,h), (h,0)):
156  *
157  *      c00*xi + c01*yi + c02
158  * ui = ---------------------
159  *      c20*xi + c21*yi + c22
160  *
161  *      c10*xi + c11*yi + c12
162  * vi = ---------------------
163  *      c20*xi + c21*yi + c22
164  *
165  * Coefficients are calculated by solving linear system:
166  * / x0 y0  1  0  0  0 -x0*u0 -y0*u0 \ /c00\ /u0\
167  * | x1 y1  1  0  0  0 -x1*u1 -y1*u1 | |c01| |u1|
168  * | x2 y2  1  0  0  0 -x2*u2 -y2*u2 | |c02| |u2|
169  * | x3 y3  1  0  0  0 -x3*u3 -y3*u3 |.|c10|=|u3|,
170  * |  0  0  0 x0 y0  1 -x0*v0 -y0*v0 | |c11| |v0|
171  * |  0  0  0 x1 y1  1 -x1*v1 -y1*v1 | |c12| |v1|
172  * |  0  0  0 x2 y2  1 -x2*v2 -y2*v2 | |c20| |v2|
173  * \  0  0  0 x3 y3  1 -x3*v3 -y3*v3 / \c21/ \v3/
174  *
175  * where:
176  *   (xi, yi) = (quad[i][0], quad[i][1])
177  *        cij - coeffs[i][j], coeffs[2][2] = 1
178  *   (ui, vi) - rectangle vertices
179  */
cvGetPerspectiveTransform(CvSize src_size,double quad[4][2],double coeffs[3][3])180 static void cvGetPerspectiveTransform( CvSize src_size, double quad[4][2], double coeffs[3][3] )
181 {
182     //CV_FUNCNAME( "cvWarpPerspective" );
183 
184     __BEGIN__;
185 
186     double a[8][8];
187     double b[8];
188 
189     CvMat A = cvMat( 8, 8, CV_64FC1, a );
190     CvMat B = cvMat( 8, 1, CV_64FC1, b );
191     CvMat X = cvMat( 8, 1, CV_64FC1, coeffs );
192 
193     int i;
194     for( i = 0; i < 4; ++i )
195     {
196         a[i][0] = quad[i][0]; a[i][1] = quad[i][1]; a[i][2] = 1;
197         a[i][3] = a[i][4] = a[i][5] = a[i][6] = a[i][7] = 0;
198         b[i] = 0;
199     }
200     for( i = 4; i < 8; ++i )
201     {
202         a[i][3] = quad[i-4][0]; a[i][4] = quad[i-4][1]; a[i][5] = 1;
203         a[i][0] = a[i][1] = a[i][2] = a[i][6] = a[i][7] = 0;
204         b[i] = 0;
205     }
206 
207     int u = src_size.width - 1;
208     int v = src_size.height - 1;
209 
210     a[1][6] = -quad[1][0] * u; a[1][7] = -quad[1][1] * u;
211     a[2][6] = -quad[2][0] * u; a[2][7] = -quad[2][1] * u;
212     b[1] = b[2] = u;
213 
214     a[6][6] = -quad[2][0] * v; a[6][7] = -quad[2][1] * v;
215     a[7][6] = -quad[3][0] * v; a[7][7] = -quad[3][1] * v;
216     b[6] = b[7] = v;
217 
218     cvSolve( &A, &B, &X );
219 
220     coeffs[2][2] = 1;
221 
222     __END__;
223 }
224 
225 /* Warps source into destination by a perspective transform */
cvWarpPerspective(CvArr * src,CvArr * dst,double quad[4][2])226 static void cvWarpPerspective( CvArr* src, CvArr* dst, double quad[4][2] )
227 {
228     CV_FUNCNAME( "cvWarpPerspective" );
229 
230     __BEGIN__;
231 
232 #ifdef __IPL_H__
233     IplImage src_stub, dst_stub;
234     IplImage* src_img;
235     IplImage* dst_img;
236     CV_CALL( src_img = cvGetImage( src, &src_stub ) );
237     CV_CALL( dst_img = cvGetImage( dst, &dst_stub ) );
238     iplWarpPerspectiveQ( src_img, dst_img, quad, IPL_WARP_R_TO_Q,
239                          IPL_INTER_CUBIC | IPL_SMOOTH_EDGE );
240 #else
241 
242     int fill_value = 0;
243 
244     double c[3][3]; /* transformation coefficients */
245     double q[4][2]; /* rearranged quad */
246 
247     int left = 0;
248     int right = 0;
249     int next_right = 0;
250     int next_left = 0;
251     double y_min = 0;
252     double y_max = 0;
253     double k_left, b_left, k_right, b_right;
254 
255     uchar* src_data;
256     int src_step;
257     CvSize src_size;
258 
259     uchar* dst_data;
260     int dst_step;
261     CvSize dst_size;
262 
263     double d = 0;
264     int direction = 0;
265     int i;
266 
267     if( !src || (!CV_IS_IMAGE( src ) && !CV_IS_MAT( src )) ||
268         cvGetElemType( src ) != CV_8UC1 ||
269         cvGetDims( src ) != 2 )
270     {
271         CV_ERROR( CV_StsBadArg,
272             "Source must be two-dimensional array of CV_8UC1 type." );
273     }
274     if( !dst || (!CV_IS_IMAGE( dst ) && !CV_IS_MAT( dst )) ||
275         cvGetElemType( dst ) != CV_8UC1 ||
276         cvGetDims( dst ) != 2 )
277     {
278         CV_ERROR( CV_StsBadArg,
279             "Destination must be two-dimensional array of CV_8UC1 type." );
280     }
281 
282     CV_CALL( cvGetRawData( src, &src_data, &src_step, &src_size ) );
283     CV_CALL( cvGetRawData( dst, &dst_data, &dst_step, &dst_size ) );
284 
285     CV_CALL( cvGetPerspectiveTransform( src_size, quad, c ) );
286 
287     /* if direction > 0 then vertices in quad follow in a CW direction,
288        otherwise they follow in a CCW direction */
289     direction = 0;
290     for( i = 0; i < 4; ++i )
291     {
292         int ni = i + 1; if( ni == 4 ) ni = 0;
293         int pi = i - 1; if( pi == -1 ) pi = 3;
294 
295         d = (quad[i][0] - quad[pi][0])*(quad[ni][1] - quad[i][1]) -
296             (quad[i][1] - quad[pi][1])*(quad[ni][0] - quad[i][0]);
297         int cur_direction = CV_SIGN(d);
298         if( direction == 0 )
299         {
300             direction = cur_direction;
301         }
302         else if( direction * cur_direction < 0 )
303         {
304             direction = 0;
305             break;
306         }
307     }
308     if( direction == 0 )
309     {
310         CV_ERROR( CV_StsBadArg, "Quadrangle is nonconvex or degenerated." );
311     }
312 
313     /* <left> is the index of the topmost quad vertice
314        if there are two such vertices <left> is the leftmost one */
315     left = 0;
316     for( i = 1; i < 4; ++i )
317     {
318         if( (quad[i][1] < quad[left][1]) ||
319             ((quad[i][1] == quad[left][1]) && (quad[i][0] < quad[left][0])) )
320         {
321             left = i;
322         }
323     }
324     /* rearrange <quad> vertices in such way that they follow in a CW
325        direction and the first vertice is the topmost one and put them
326        into <q> */
327     if( direction > 0 )
328     {
329         for( i = left; i < 4; ++i )
330         {
331             q[i-left][0] = quad[i][0];
332             q[i-left][1] = quad[i][1];
333         }
334         for( i = 0; i < left; ++i )
335         {
336             q[4-left+i][0] = quad[i][0];
337             q[4-left+i][1] = quad[i][1];
338         }
339     }
340     else
341     {
342         for( i = left; i >= 0; --i )
343         {
344             q[left-i][0] = quad[i][0];
345             q[left-i][1] = quad[i][1];
346         }
347         for( i = 3; i > left; --i )
348         {
349             q[4+left-i][0] = quad[i][0];
350             q[4+left-i][1] = quad[i][1];
351         }
352     }
353 
354     left = right = 0;
355     /* if there are two topmost points, <right> is the index of the rightmost one
356        otherwise <right> */
357     if( q[left][1] == q[left+1][1] )
358     {
359         right = 1;
360     }
361 
362     /* <next_left> follows <left> in a CCW direction */
363     next_left = 3;
364     /* <next_right> follows <right> in a CW direction */
365     next_right = right + 1;
366 
367     /* subtraction of 1 prevents skipping of the first row */
368     y_min = q[left][1] - 1;
369 
370     /* left edge equation: y = k_left * x + b_left */
371     k_left = (q[left][0] - q[next_left][0]) /
372                (q[left][1] - q[next_left][1]);
373     b_left = (q[left][1] * q[next_left][0] -
374                q[left][0] * q[next_left][1]) /
375                  (q[left][1] - q[next_left][1]);
376 
377     /* right edge equation: y = k_right * x + b_right */
378     k_right = (q[right][0] - q[next_right][0]) /
379                (q[right][1] - q[next_right][1]);
380     b_right = (q[right][1] * q[next_right][0] -
381                q[right][0] * q[next_right][1]) /
382                  (q[right][1] - q[next_right][1]);
383 
384     for(;;)
385     {
386         int x, y;
387 
388         y_max = MIN( q[next_left][1], q[next_right][1] );
389 
390         int iy_min = MAX( cvRound(y_min), 0 ) + 1;
391         int iy_max = MIN( cvRound(y_max), dst_size.height - 1 );
392 
393         double x_min = k_left * iy_min + b_left;
394         double x_max = k_right * iy_min + b_right;
395 
396         /* walk through the destination quadrangle row by row */
397         for( y = iy_min; y <= iy_max; ++y )
398         {
399             int ix_min = MAX( cvRound( x_min ), 0 );
400             int ix_max = MIN( cvRound( x_max ), dst_size.width - 1 );
401 
402             for( x = ix_min; x <= ix_max; ++x )
403             {
404                 /* calculate coordinates of the corresponding source array point */
405                 double div = (c[2][0] * x + c[2][1] * y + c[2][2]);
406                 double src_x = (c[0][0] * x + c[0][1] * y + c[0][2]) / div;
407                 double src_y = (c[1][0] * x + c[1][1] * y + c[1][2]) / div;
408 
409                 int isrc_x = cvFloor( src_x );
410                 int isrc_y = cvFloor( src_y );
411                 double delta_x = src_x - isrc_x;
412                 double delta_y = src_y - isrc_y;
413 
414                 uchar* s = src_data + isrc_y * src_step + isrc_x;
415 
416                 int i00, i10, i01, i11;
417                 i00 = i10 = i01 = i11 = (int) fill_value;
418 
419                 /* linear interpolation using 2x2 neighborhood */
420                 if( isrc_x >= 0 && isrc_x <= src_size.width &&
421                     isrc_y >= 0 && isrc_y <= src_size.height )
422                 {
423                     i00 = s[0];
424                 }
425                 if( isrc_x >= -1 && isrc_x < src_size.width &&
426                     isrc_y >= 0 && isrc_y <= src_size.height )
427                 {
428                     i10 = s[1];
429                 }
430                 if( isrc_x >= 0 && isrc_x <= src_size.width &&
431                     isrc_y >= -1 && isrc_y < src_size.height )
432                 {
433                     i01 = s[src_step];
434                 }
435                 if( isrc_x >= -1 && isrc_x < src_size.width &&
436                     isrc_y >= -1 && isrc_y < src_size.height )
437                 {
438                     i11 = s[src_step+1];
439                 }
440 
441                 double i0 = i00 + (i10 - i00)*delta_x;
442                 double i1 = i01 + (i11 - i01)*delta_x;
443 
444                 ((uchar*)(dst_data + y * dst_step))[x] = (uchar) (i0 + (i1 - i0)*delta_y);
445             }
446             x_min += k_left;
447             x_max += k_right;
448         }
449 
450         if( (next_left == next_right) ||
451             (next_left+1 == next_right && q[next_left][1] == q[next_right][1]) )
452         {
453             break;
454         }
455 
456         if( y_max == q[next_left][1] )
457         {
458             left = next_left;
459             next_left = left - 1;
460 
461             k_left = (q[left][0] - q[next_left][0]) /
462                        (q[left][1] - q[next_left][1]);
463             b_left = (q[left][1] * q[next_left][0] -
464                        q[left][0] * q[next_left][1]) /
465                          (q[left][1] - q[next_left][1]);
466         }
467         if( y_max == q[next_right][1] )
468         {
469             right = next_right;
470             next_right = right + 1;
471 
472             k_right = (q[right][0] - q[next_right][0]) /
473                        (q[right][1] - q[next_right][1]);
474             b_right = (q[right][1] * q[next_right][0] -
475                        q[right][0] * q[next_right][1]) /
476                          (q[right][1] - q[next_right][1]);
477         }
478         y_min = y_max;
479     }
480 #endif /* #ifndef __IPL_H__ */
481 
482     __END__;
483 }
484 
485 static
icvRandomQuad(int width,int height,double quad[4][2],double maxxangle,double maxyangle,double maxzangle)486 void icvRandomQuad( int width, int height, double quad[4][2],
487                     double maxxangle,
488                     double maxyangle,
489                     double maxzangle )
490 {
491     double distfactor = 3.0;
492     double distfactor2 = 1.0;
493 
494     double halfw, halfh;
495     int i;
496 
497     double rotVectData[3];
498     double vectData[3];
499     double rotMatData[9];
500 
501     CvMat rotVect;
502     CvMat rotMat;
503     CvMat vect;
504 
505     double d;
506 
507     rotVect = cvMat( 3, 1, CV_64FC1, &rotVectData[0] );
508     rotMat = cvMat( 3, 3, CV_64FC1, &rotMatData[0] );
509     vect = cvMat( 3, 1, CV_64FC1, &vectData[0] );
510 
511     rotVectData[0] = maxxangle * (2.0 * rand() / RAND_MAX - 1.0);
512     rotVectData[1] = ( maxyangle - fabs( rotVectData[0] ) )
513         * (2.0 * rand() / RAND_MAX - 1.0);
514     rotVectData[2] = maxzangle * (2.0 * rand() / RAND_MAX - 1.0);
515     d = (distfactor + distfactor2 * (2.0 * rand() / RAND_MAX - 1.0)) * width;
516 
517 /*
518     rotVectData[0] = maxxangle;
519     rotVectData[1] = maxyangle;
520     rotVectData[2] = maxzangle;
521 
522     d = distfactor * width;
523 */
524 
525     cvRodrigues2( &rotVect, &rotMat );
526 
527     halfw = 0.5 * width;
528     halfh = 0.5 * height;
529 
530     quad[0][0] = -halfw;
531     quad[0][1] = -halfh;
532     quad[1][0] =  halfw;
533     quad[1][1] = -halfh;
534     quad[2][0] =  halfw;
535     quad[2][1] =  halfh;
536     quad[3][0] = -halfw;
537     quad[3][1] =  halfh;
538 
539     for( i = 0; i < 4; i++ )
540     {
541         rotVectData[0] = quad[i][0];
542         rotVectData[1] = quad[i][1];
543         rotVectData[2] = 0.0;
544         cvMatMulAdd( &rotMat, &rotVect, 0, &vect );
545         quad[i][0] = vectData[0] * d / (d + vectData[2]) + halfw;
546         quad[i][1] = vectData[1] * d / (d + vectData[2]) + halfh;
547 
548         /*
549         quad[i][0] += halfw;
550         quad[i][1] += halfh;
551         */
552     }
553 }
554 
555 
556 typedef struct CvSampleDistortionData
557 {
558     IplImage* src;
559     IplImage* erode;
560     IplImage* dilate;
561     IplImage* mask;
562     IplImage* img;
563     IplImage* maskimg;
564     int dx;
565     int dy;
566     int bgcolor;
567 } CvSampleDistortionData;
568 
569 #if defined CV_OPENMP && (defined _MSC_VER || defined CV_ICC)
570 #define CV_OPENMP 1
571 #else
572 #undef CV_OPENMP
573 #endif
574 
575 typedef struct CvBackgroundData
576 {
577     int    count;
578     char** filename;
579     int    last;
580     int    round;
581     CvSize winsize;
582 } CvBackgroundData;
583 
584 typedef struct CvBackgroundReader
585 {
586     CvMat   src;
587     CvMat   img;
588     CvPoint offset;
589     float   scale;
590     float   scalefactor;
591     float   stepfactor;
592     CvPoint point;
593 } CvBackgroundReader;
594 
595 /*
596  * Background reader
597  * Created in each thread
598  */
599 CvBackgroundReader* cvbgreader = NULL;
600 
601 #if defined CV_OPENMP
602 #pragma omp threadprivate(cvbgreader)
603 #endif
604 
605 CvBackgroundData* cvbgdata = NULL;
606 
icvStartSampleDistortion(const char * imgfilename,int bgcolor,int bgthreshold,CvSampleDistortionData * data)607 static int icvStartSampleDistortion( const char* imgfilename, int bgcolor, int bgthreshold,
608                               CvSampleDistortionData* data )
609 {
610     memset( data, 0, sizeof( *data ) );
611     data->src = cvLoadImage( imgfilename, 0 );
612     if( data->src != NULL && data->src->nChannels == 1
613         && data->src->depth == IPL_DEPTH_8U )
614     {
615         int r, c;
616         uchar* pmask;
617         uchar* psrc;
618         uchar* perode;
619         uchar* pdilate;
620         uchar dd, de;
621 
622         data->dx = data->src->width / 2;
623         data->dy = data->src->height / 2;
624         data->bgcolor = bgcolor;
625 
626         data->mask = cvCloneImage( data->src );
627         data->erode = cvCloneImage( data->src );
628         data->dilate = cvCloneImage( data->src );
629 
630         /* make mask image */
631         for( r = 0; r < data->mask->height; r++ )
632         {
633             for( c = 0; c < data->mask->width; c++ )
634             {
635                 pmask = ( (uchar*) (data->mask->imageData + r * data->mask->widthStep)
636                         + c );
637                 if( bgcolor - bgthreshold <= (int) (*pmask) &&
638                     (int) (*pmask) <= bgcolor + bgthreshold )
639                 {
640                     *pmask = (uchar) 0;
641                 }
642                 else
643                 {
644                     *pmask = (uchar) 255;
645                 }
646             }
647         }
648 
649         /* extend borders of source image */
650         cvErode( data->src, data->erode, 0, 1 );
651         cvDilate( data->src, data->dilate, 0, 1 );
652         for( r = 0; r < data->mask->height; r++ )
653         {
654             for( c = 0; c < data->mask->width; c++ )
655             {
656                 pmask = ( (uchar*) (data->mask->imageData + r * data->mask->widthStep)
657                         + c );
658                 if( (*pmask) == 0 )
659                 {
660                     psrc = ( (uchar*) (data->src->imageData + r * data->src->widthStep)
661                            + c );
662                     perode =
663                         ( (uchar*) (data->erode->imageData + r * data->erode->widthStep)
664                                 + c );
665                     pdilate =
666                         ( (uchar*)(data->dilate->imageData + r * data->dilate->widthStep)
667                                 + c );
668                     de = (uchar)(bgcolor - (*perode));
669                     dd = (uchar)((*pdilate) - bgcolor);
670                     if( de >= dd && de > bgthreshold )
671                     {
672                         (*psrc) = (*perode);
673                     }
674                     if( dd > de && dd > bgthreshold )
675                     {
676                         (*psrc) = (*pdilate);
677                     }
678                 }
679             }
680         }
681 
682         data->img = cvCreateImage( cvSize( data->src->width + 2 * data->dx,
683                                            data->src->height + 2 * data->dy ),
684                                    IPL_DEPTH_8U, 1 );
685         data->maskimg = cvCloneImage( data->img );
686 
687         return 1;
688     }
689 
690     return 0;
691 }
692 
693 static
icvPlaceDistortedSample(CvArr * background,int inverse,int maxintensitydev,double maxxangle,double maxyangle,double maxzangle,int inscribe,double maxshiftf,double maxscalef,CvSampleDistortionData * data)694 void icvPlaceDistortedSample( CvArr* background,
695                               int inverse, int maxintensitydev,
696                               double maxxangle, double maxyangle, double maxzangle,
697                               int inscribe, double maxshiftf, double maxscalef,
698                               CvSampleDistortionData* data )
699 {
700     double quad[4][2];
701     int r, c;
702     uchar* pimg;
703     uchar* pbg;
704     uchar* palpha;
705     uchar chartmp;
706     int forecolordev;
707     float scale;
708     IplImage* img;
709     IplImage* maskimg;
710     CvMat  stub;
711     CvMat* bgimg;
712 
713     CvRect cr;
714     CvRect roi;
715 
716     double xshift, yshift, randscale;
717 
718     icvRandomQuad( data->src->width, data->src->height, quad,
719                    maxxangle, maxyangle, maxzangle );
720     quad[0][0] += (double) data->dx;
721     quad[0][1] += (double) data->dy;
722     quad[1][0] += (double) data->dx;
723     quad[1][1] += (double) data->dy;
724     quad[2][0] += (double) data->dx;
725     quad[2][1] += (double) data->dy;
726     quad[3][0] += (double) data->dx;
727     quad[3][1] += (double) data->dy;
728 
729     cvSet( data->img, cvScalar( data->bgcolor ) );
730     cvSet( data->maskimg, cvScalar( 0.0 ) );
731 
732     cvWarpPerspective( data->src, data->img, quad );
733     cvWarpPerspective( data->mask, data->maskimg, quad );
734 
735     cvSmooth( data->maskimg, data->maskimg, CV_GAUSSIAN, 3, 3 );
736 
737     bgimg = cvGetMat( background, &stub );
738 
739     cr.x = data->dx;
740     cr.y = data->dy;
741     cr.width = data->src->width;
742     cr.height = data->src->height;
743 
744     if( inscribe )
745     {
746         /* quad's circumscribing rectangle */
747         cr.x = (int) MIN( quad[0][0], quad[3][0] );
748         cr.y = (int) MIN( quad[0][1], quad[1][1] );
749         cr.width  = (int) (MAX( quad[1][0], quad[2][0] ) + 0.5F ) - cr.x;
750         cr.height = (int) (MAX( quad[2][1], quad[3][1] ) + 0.5F ) - cr.y;
751     }
752 
753     xshift = maxshiftf * rand() / RAND_MAX;
754     yshift = maxshiftf * rand() / RAND_MAX;
755 
756     cr.x -= (int) ( xshift * cr.width  );
757     cr.y -= (int) ( yshift * cr.height );
758     cr.width  = (int) ((1.0 + maxshiftf) * cr.width );
759     cr.height = (int) ((1.0 + maxshiftf) * cr.height);
760 
761     randscale = maxscalef * rand() / RAND_MAX;
762     cr.x -= (int) ( 0.5 * randscale * cr.width  );
763     cr.y -= (int) ( 0.5 * randscale * cr.height );
764     cr.width  = (int) ((1.0 + randscale) * cr.width );
765     cr.height = (int) ((1.0 + randscale) * cr.height);
766 
767     scale = MAX( ((float) cr.width) / bgimg->cols, ((float) cr.height) / bgimg->rows );
768 
769     roi.x = (int) (-0.5F * (scale * bgimg->cols - cr.width) + cr.x);
770     roi.y = (int) (-0.5F * (scale * bgimg->rows - cr.height) + cr.y);
771     roi.width  = (int) (scale * bgimg->cols);
772     roi.height = (int) (scale * bgimg->rows);
773 
774     img = cvCreateImage( cvSize( bgimg->cols, bgimg->rows ), IPL_DEPTH_8U, 1 );
775     maskimg = cvCreateImage( cvSize( bgimg->cols, bgimg->rows ), IPL_DEPTH_8U, 1 );
776 
777     cvSetImageROI( data->img, roi );
778     cvResize( data->img, img );
779     cvResetImageROI( data->img );
780     cvSetImageROI( data->maskimg, roi );
781     cvResize( data->maskimg, maskimg );
782     cvResetImageROI( data->maskimg );
783 
784     forecolordev = (int) (maxintensitydev * (2.0 * rand() / RAND_MAX - 1.0));
785 
786     for( r = 0; r < img->height; r++ )
787     {
788         for( c = 0; c < img->width; c++ )
789         {
790             pimg = (uchar*) img->imageData + r * img->widthStep + c;
791             pbg = (uchar*) bgimg->data.ptr + r * bgimg->step + c;
792             palpha = (uchar*) maskimg->imageData + r * maskimg->widthStep + c;
793             chartmp = (uchar) MAX( 0, MIN( 255, forecolordev + (*pimg) ) );
794             if( inverse )
795             {
796                 chartmp ^= 0xFF;
797             }
798             *pbg = (uchar) (( chartmp*(*palpha )+(255 - (*palpha) )*(*pbg) ) / 255);
799         }
800     }
801 
802     cvReleaseImage( &img );
803     cvReleaseImage( &maskimg );
804 }
805 
806 static
icvEndSampleDistortion(CvSampleDistortionData * data)807 void icvEndSampleDistortion( CvSampleDistortionData* data )
808 {
809     if( data->src )
810     {
811         cvReleaseImage( &data->src );
812     }
813     if( data->mask )
814     {
815         cvReleaseImage( &data->mask );
816     }
817     if( data->erode )
818     {
819         cvReleaseImage( &data->erode );
820     }
821     if( data->dilate )
822     {
823         cvReleaseImage( &data->dilate );
824     }
825     if( data->img )
826     {
827         cvReleaseImage( &data->img );
828     }
829     if( data->maskimg )
830     {
831         cvReleaseImage( &data->maskimg );
832     }
833 }
834 
835 static
icvCreateBackgroundData(const char * filename,CvSize winsize)836 CvBackgroundData* icvCreateBackgroundData( const char* filename, CvSize winsize )
837 {
838     CvBackgroundData* data = NULL;
839 
840     const char* dir = NULL;
841     char full[PATH_MAX];
842     char* imgfilename = NULL;
843     size_t datasize = 0;
844     int    count = 0;
845     FILE*  input = NULL;
846     char*  tmp   = NULL;
847     int    len   = 0;
848 
849     assert( filename != NULL );
850 
851     dir = strrchr( filename, '\\' );
852     if( dir == NULL )
853     {
854         dir = strrchr( filename, '/' );
855     }
856     if( dir == NULL )
857     {
858         imgfilename = &(full[0]);
859     }
860     else
861     {
862         strncpy( &(full[0]), filename, (dir - filename + 1) );
863         imgfilename = &(full[(dir - filename + 1)]);
864     }
865 
866     input = fopen( filename, "r" );
867     if( input != NULL )
868     {
869         count = 0;
870         datasize = 0;
871 
872         /* count */
873         while( !feof( input ) )
874         {
875             *imgfilename = '\0';
876             if( !fgets( imgfilename, PATH_MAX - (int)(imgfilename - full) - 1, input ))
877                 break;
878             len = (int)strlen( imgfilename );
879             for( ; len > 0 && isspace(imgfilename[len-1]); len-- )
880                 imgfilename[len-1] = '\0';
881             if( len > 0 )
882             {
883                 if( (*imgfilename) == '#' ) continue; /* comment */
884                 count++;
885                 datasize += sizeof( char ) * (strlen( &(full[0]) ) + 1);
886             }
887         }
888         if( count > 0 )
889         {
890             //rewind( input );
891             fseek( input, 0, SEEK_SET );
892             datasize += sizeof( *data ) + sizeof( char* ) * count;
893             data = (CvBackgroundData*) cvAlloc( datasize );
894             memset( (void*) data, 0, datasize );
895             data->count = count;
896             data->filename = (char**) (data + 1);
897             data->last = 0;
898             data->round = 0;
899             data->winsize = winsize;
900             tmp = (char*) (data->filename + data->count);
901             count = 0;
902             while( !feof( input ) )
903             {
904                 *imgfilename = '\0';
905                 if( !fgets( imgfilename, PATH_MAX - (int)(imgfilename - full) - 1, input ))
906                     break;
907                 len = (int)strlen( imgfilename );
908                 if( len > 0 && imgfilename[len-1] == '\n' )
909                     imgfilename[len-1] = 0, len--;
910                 if( len > 0 )
911                 {
912                     if( (*imgfilename) == '#' ) continue; /* comment */
913                     data->filename[count++] = tmp;
914                     strcpy( tmp, &(full[0]) );
915                     tmp += strlen( &(full[0]) ) + 1;
916                 }
917             }
918         }
919         fclose( input );
920     }
921 
922     return data;
923 }
924 
925 static
icvReleaseBackgroundData(CvBackgroundData ** data)926 void icvReleaseBackgroundData( CvBackgroundData** data )
927 {
928     assert( data != NULL && (*data) != NULL );
929 
930     cvFree( data );
931 }
932 
933 static
icvCreateBackgroundReader()934 CvBackgroundReader* icvCreateBackgroundReader()
935 {
936     CvBackgroundReader* reader = NULL;
937 
938     reader = (CvBackgroundReader*) cvAlloc( sizeof( *reader ) );
939     memset( (void*) reader, 0, sizeof( *reader ) );
940     reader->src = cvMat( 0, 0, CV_8UC1, NULL );
941     reader->img = cvMat( 0, 0, CV_8UC1, NULL );
942     reader->offset = cvPoint( 0, 0 );
943     reader->scale       = 1.0F;
944     reader->scalefactor = 1.4142135623730950488016887242097F;
945     reader->stepfactor  = 0.5F;
946     reader->point = reader->offset;
947 
948     return reader;
949 }
950 
951 static
icvReleaseBackgroundReader(CvBackgroundReader ** reader)952 void icvReleaseBackgroundReader( CvBackgroundReader** reader )
953 {
954     assert( reader != NULL && (*reader) != NULL );
955 
956     if( (*reader)->src.data.ptr != NULL )
957     {
958         cvFree( &((*reader)->src.data.ptr) );
959     }
960     if( (*reader)->img.data.ptr != NULL )
961     {
962         cvFree( &((*reader)->img.data.ptr) );
963     }
964 
965     cvFree( reader );
966 }
967 
968 static
icvGetNextFromBackgroundData(CvBackgroundData * data,CvBackgroundReader * reader)969 void icvGetNextFromBackgroundData( CvBackgroundData* data,
970                                    CvBackgroundReader* reader )
971 {
972     IplImage* img = NULL;
973     size_t datasize = 0;
974     int round = 0;
975     int i = 0;
976     CvPoint offset = cvPoint(0,0);
977 
978     assert( data != NULL && reader != NULL );
979 
980     if( reader->src.data.ptr != NULL )
981     {
982         cvFree( &(reader->src.data.ptr) );
983         reader->src.data.ptr = NULL;
984     }
985     if( reader->img.data.ptr != NULL )
986     {
987         cvFree( &(reader->img.data.ptr) );
988         reader->img.data.ptr = NULL;
989     }
990 
991     #ifdef CV_OPENMP
992     #pragma omp critical(c_background_data)
993     #endif /* CV_OPENMP */
994     {
995         for( i = 0; i < data->count; i++ )
996         {
997             round = data->round;
998 
999 #ifdef CV_VERBOSE
1000             printf( "Open background image: %s\n", data->filename[data->last] );
1001 #endif /* CV_VERBOSE */
1002 
1003             data->last = rand() % data->count;
1004             data->last %= data->count;
1005             img = cvLoadImage( data->filename[data->last], 0 );
1006             if( !img )
1007                 continue;
1008             data->round += data->last / data->count;
1009             data->round = data->round % (data->winsize.width * data->winsize.height);
1010 
1011             offset.x = round % data->winsize.width;
1012             offset.y = round / data->winsize.width;
1013 
1014             offset.x = MIN( offset.x, img->width - data->winsize.width );
1015             offset.y = MIN( offset.y, img->height - data->winsize.height );
1016 
1017             if( img != NULL && img->depth == IPL_DEPTH_8U && img->nChannels == 1 &&
1018                 offset.x >= 0 && offset.y >= 0 )
1019             {
1020                 break;
1021             }
1022             if( img != NULL )
1023                 cvReleaseImage( &img );
1024             img = NULL;
1025         }
1026     }
1027     if( img == NULL )
1028     {
1029         /* no appropriate image */
1030 
1031 #ifdef CV_VERBOSE
1032         printf( "Invalid background description file.\n" );
1033 #endif /* CV_VERBOSE */
1034 
1035         assert( 0 );
1036         exit( 1 );
1037     }
1038     datasize = sizeof( uchar ) * img->width * img->height;
1039     reader->src = cvMat( img->height, img->width, CV_8UC1, (void*) cvAlloc( datasize ) );
1040     cvCopy( img, &reader->src, NULL );
1041     cvReleaseImage( &img );
1042     img = NULL;
1043 
1044     //reader->offset.x = round % data->winsize.width;
1045     //reader->offset.y = round / data->winsize.width;
1046     reader->offset = offset;
1047     reader->point = reader->offset;
1048     reader->scale = MAX(
1049         ((float) data->winsize.width + reader->point.x) / ((float) reader->src.cols),
1050         ((float) data->winsize.height + reader->point.y) / ((float) reader->src.rows) );
1051 
1052     reader->img = cvMat( (int) (reader->scale * reader->src.rows + 0.5F),
1053                          (int) (reader->scale * reader->src.cols + 0.5F),
1054                           CV_8UC1, (void*) cvAlloc( datasize ) );
1055     cvResize( &(reader->src), &(reader->img) );
1056 }
1057 
1058 /*
1059  * icvGetBackgroundImage
1060  *
1061  * Get an image from background
1062  * <img> must be allocated and have size, previously passed to icvInitBackgroundReaders
1063  *
1064  * Usage example:
1065  * icvInitBackgroundReaders( "bg.txt", cvSize( 24, 24 ) );
1066  * ...
1067  * #pragma omp parallel
1068  * {
1069  *     ...
1070  *     icvGetBackgourndImage( cvbgdata, cvbgreader, img );
1071  *     ...
1072  * }
1073  * ...
1074  * icvDestroyBackgroundReaders();
1075  */
1076 static
icvGetBackgroundImage(CvBackgroundData * data,CvBackgroundReader * reader,CvMat * img)1077 void icvGetBackgroundImage( CvBackgroundData* data,
1078                             CvBackgroundReader* reader,
1079                             CvMat* img )
1080 {
1081     CvMat mat;
1082 
1083     assert( data != NULL && reader != NULL && img != NULL );
1084     assert( CV_MAT_TYPE( img->type ) == CV_8UC1 );
1085     assert( img->cols == data->winsize.width );
1086     assert( img->rows == data->winsize.height );
1087 
1088     if( reader->img.data.ptr == NULL )
1089     {
1090         icvGetNextFromBackgroundData( data, reader );
1091     }
1092 
1093     mat = cvMat( data->winsize.height, data->winsize.width, CV_8UC1 );
1094     cvSetData( &mat, (void*) (reader->img.data.ptr + reader->point.y * reader->img.step
1095                               + reader->point.x * sizeof( uchar )), reader->img.step );
1096 
1097     cvCopy( &mat, img, 0 );
1098     if( (int) ( reader->point.x + (1.0F + reader->stepfactor ) * data->winsize.width )
1099             < reader->img.cols )
1100     {
1101         reader->point.x += (int) (reader->stepfactor * data->winsize.width);
1102     }
1103     else
1104     {
1105         reader->point.x = reader->offset.x;
1106         if( (int) ( reader->point.y + (1.0F + reader->stepfactor ) * data->winsize.height )
1107                 < reader->img.rows )
1108         {
1109             reader->point.y += (int) (reader->stepfactor * data->winsize.height);
1110         }
1111         else
1112         {
1113             reader->point.y = reader->offset.y;
1114             reader->scale *= reader->scalefactor;
1115             if( reader->scale <= 1.0F )
1116             {
1117                 reader->img = cvMat( (int) (reader->scale * reader->src.rows),
1118                                      (int) (reader->scale * reader->src.cols),
1119                                       CV_8UC1, (void*) (reader->img.data.ptr) );
1120                 cvResize( &(reader->src), &(reader->img) );
1121             }
1122             else
1123             {
1124                 icvGetNextFromBackgroundData( data, reader );
1125             }
1126         }
1127     }
1128 }
1129 
1130 /*
1131  * icvInitBackgroundReaders
1132  *
1133  * Initialize background reading process.
1134  * <cvbgreader> and <cvbgdata> are initialized.
1135  * Must be called before any usage of background
1136  *
1137  * filename - name of background description file
1138  * winsize  - size of images will be obtained from background
1139  *
1140  * return 1 on success, 0 otherwise.
1141  */
icvInitBackgroundReaders(const char * filename,CvSize winsize)1142 static int icvInitBackgroundReaders( const char* filename, CvSize winsize )
1143 {
1144     if( cvbgdata == NULL && filename != NULL )
1145     {
1146         cvbgdata = icvCreateBackgroundData( filename, winsize );
1147     }
1148 
1149     if( cvbgdata )
1150     {
1151 
1152         #ifdef CV_OPENMP
1153         #pragma omp parallel
1154         #endif /* CV_OPENMP */
1155         {
1156             #ifdef CV_OPENMP
1157             #pragma omp critical(c_create_bg_data)
1158             #endif /* CV_OPENMP */
1159             {
1160                 if( cvbgreader == NULL )
1161                 {
1162                     cvbgreader = icvCreateBackgroundReader();
1163                 }
1164             }
1165         }
1166 
1167     }
1168 
1169     return (cvbgdata != NULL);
1170 }
1171 
1172 /*
1173  * icvDestroyBackgroundReaders
1174  *
1175  * Finish backgournd reading process
1176  */
1177 static
icvDestroyBackgroundReaders()1178 void icvDestroyBackgroundReaders()
1179 {
1180     /* release background reader in each thread */
1181     #ifdef CV_OPENMP
1182     #pragma omp parallel
1183     #endif /* CV_OPENMP */
1184     {
1185         #ifdef CV_OPENMP
1186         #pragma omp critical(c_release_bg_data)
1187         #endif /* CV_OPENMP */
1188         {
1189             if( cvbgreader != NULL )
1190             {
1191                 icvReleaseBackgroundReader( &cvbgreader );
1192                 cvbgreader = NULL;
1193             }
1194         }
1195     }
1196 
1197     if( cvbgdata != NULL )
1198     {
1199         icvReleaseBackgroundData( &cvbgdata );
1200         cvbgdata = NULL;
1201     }
1202 }
1203 
cvCreateTrainingSamples(const char * filename,const char * imgfilename,int bgcolor,int bgthreshold,const char * bgfilename,int count,int invert,int maxintensitydev,double maxxangle,double maxyangle,double maxzangle,int showsamples,int winwidth,int winheight)1204 void cvCreateTrainingSamples( const char* filename,
1205                               const char* imgfilename, int bgcolor, int bgthreshold,
1206                               const char* bgfilename, int count,
1207                               int invert, int maxintensitydev,
1208                               double maxxangle, double maxyangle, double maxzangle,
1209                               int showsamples,
1210                               int winwidth, int winheight )
1211 {
1212     CvSampleDistortionData data;
1213 
1214     assert( filename != NULL );
1215     assert( imgfilename != NULL );
1216 
1217     if( !icvMkDir( filename ) )
1218     {
1219         fprintf( stderr, "Unable to create output file: %s\n", filename );
1220         return;
1221     }
1222     if( icvStartSampleDistortion( imgfilename, bgcolor, bgthreshold, &data ) )
1223     {
1224         FILE* output = NULL;
1225 
1226         output = fopen( filename, "wb" );
1227         if( output != NULL )
1228         {
1229             int hasbg;
1230             int i;
1231             CvMat sample;
1232             int inverse;
1233 
1234             hasbg = 0;
1235             hasbg = (bgfilename != NULL && icvInitBackgroundReaders( bgfilename,
1236                      cvSize( winwidth,winheight ) ) );
1237 
1238             sample = cvMat( winheight, winwidth, CV_8UC1, cvAlloc( sizeof( uchar ) *
1239                             winheight * winwidth ) );
1240 
1241             icvWriteVecHeader( output, count, sample.cols, sample.rows );
1242 
1243             if( showsamples )
1244             {
1245                 cvNamedWindow( "Sample", CV_WINDOW_AUTOSIZE );
1246             }
1247 
1248             inverse = invert;
1249             for( i = 0; i < count; i++ )
1250             {
1251                 if( hasbg )
1252                 {
1253                     icvGetBackgroundImage( cvbgdata, cvbgreader, &sample );
1254                 }
1255                 else
1256                 {
1257                     cvSet( &sample, cvScalar( bgcolor ) );
1258                 }
1259 
1260                 if( invert == CV_RANDOM_INVERT )
1261                 {
1262                     inverse = (rand() > (RAND_MAX/2));
1263                 }
1264                 icvPlaceDistortedSample( &sample, inverse, maxintensitydev,
1265                     maxxangle, maxyangle, maxzangle,
1266                     0   /* nonzero means placing image without cut offs */,
1267                     0.0 /* nozero adds random shifting                  */,
1268                     0.0 /* nozero adds random scaling                   */,
1269                     &data );
1270 
1271                 if( showsamples )
1272                 {
1273                     cvShowImage( "Sample", &sample );
1274                     if( cvWaitKey( 0 ) == 27 )
1275                     {
1276                         showsamples = 0;
1277                     }
1278                 }
1279 
1280                 icvWriteVecSample( output, &sample );
1281 
1282 #ifdef CV_VERBOSE
1283                 if( i % 500 == 0 )
1284                 {
1285                     printf( "\r%3d%%", 100 * i / count );
1286                 }
1287 #endif /* CV_VERBOSE */
1288             }
1289             icvDestroyBackgroundReaders();
1290             cvFree( &(sample.data.ptr) );
1291             fclose( output );
1292         } /* if( output != NULL ) */
1293 
1294         icvEndSampleDistortion( &data );
1295     }
1296 
1297 #ifdef CV_VERBOSE
1298     printf( "\r      \r" );
1299 #endif /* CV_VERBOSE */
1300 
1301 }
1302 
1303 #define CV_INFO_FILENAME "info.dat"
1304 
cvCreateTestSamples(const char * infoname,const char * imgfilename,int bgcolor,int bgthreshold,const char * bgfilename,int count,int invert,int maxintensitydev,double maxxangle,double maxyangle,double maxzangle,int showsamples,int winwidth,int winheight)1305 void cvCreateTestSamples( const char* infoname,
1306                           const char* imgfilename, int bgcolor, int bgthreshold,
1307                           const char* bgfilename, int count,
1308                           int invert, int maxintensitydev,
1309                           double maxxangle, double maxyangle, double maxzangle,
1310                           int showsamples,
1311                           int winwidth, int winheight )
1312 {
1313     CvSampleDistortionData data;
1314 
1315     assert( infoname != NULL );
1316     assert( imgfilename != NULL );
1317     assert( bgfilename != NULL );
1318 
1319     if( !icvMkDir( infoname ) )
1320     {
1321 
1322 #if CV_VERBOSE
1323         fprintf( stderr, "Unable to create directory hierarchy: %s\n", infoname );
1324 #endif /* CV_VERBOSE */
1325 
1326         return;
1327     }
1328     if( icvStartSampleDistortion( imgfilename, bgcolor, bgthreshold, &data ) )
1329     {
1330         char fullname[PATH_MAX];
1331         char* filename;
1332         CvMat win;
1333         FILE* info;
1334 
1335         if( icvInitBackgroundReaders( bgfilename, cvSize( 10, 10 ) ) )
1336         {
1337             int i;
1338             int x, y, width, height;
1339             float scale;
1340             float maxscale;
1341             int inverse;
1342 
1343             if( showsamples )
1344             {
1345                 cvNamedWindow( "Image", CV_WINDOW_AUTOSIZE );
1346             }
1347 
1348             info = fopen( infoname, "w" );
1349             strcpy( fullname, infoname );
1350             filename = strrchr( fullname, '\\' );
1351             if( filename == NULL )
1352             {
1353                 filename = strrchr( fullname, '/' );
1354             }
1355             if( filename == NULL )
1356             {
1357                 filename = fullname;
1358             }
1359             else
1360             {
1361                 filename++;
1362             }
1363 
1364             count = MIN( count, cvbgdata->count );
1365             inverse = invert;
1366             for( i = 0; i < count; i++ )
1367             {
1368                 icvGetNextFromBackgroundData( cvbgdata, cvbgreader );
1369 
1370                 maxscale = MIN( 0.7F * cvbgreader->src.cols / winwidth,
1371                                    0.7F * cvbgreader->src.rows / winheight );
1372                 if( maxscale < 1.0F ) continue;
1373 
1374                 scale = (maxscale - 1.0F) * rand() / RAND_MAX + 1.0F;
1375                 width = (int) (scale * winwidth);
1376                 height = (int) (scale * winheight);
1377                 x = (int) ((0.1+0.8 * rand()/RAND_MAX) * (cvbgreader->src.cols - width));
1378                 y = (int) ((0.1+0.8 * rand()/RAND_MAX) * (cvbgreader->src.rows - height));
1379 
1380                 cvGetSubArr( &cvbgreader->src, &win, cvRect( x, y ,width, height ) );
1381                 if( invert == CV_RANDOM_INVERT )
1382                 {
1383                     inverse = (rand() > (RAND_MAX/2));
1384                 }
1385                 icvPlaceDistortedSample( &win, inverse, maxintensitydev,
1386                                          maxxangle, maxyangle, maxzangle,
1387                                          1, 0.0, 0.0, &data );
1388 
1389 
1390                 sprintf( filename, "%04d_%04d_%04d_%04d_%04d.jpg",
1391                          (i + 1), x, y, width, height );
1392 
1393                 if( info )
1394                 {
1395                     fprintf( info, "%s %d %d %d %d %d\n",
1396                         filename, 1, x, y, width, height );
1397                 }
1398 
1399                 cvSaveImage( fullname, &cvbgreader->src );
1400                 if( showsamples )
1401                 {
1402                     cvShowImage( "Image", &cvbgreader->src );
1403                     if( cvWaitKey( 0 ) == 27 )
1404                     {
1405                         showsamples = 0;
1406                     }
1407                 }
1408             }
1409             if( info ) fclose( info );
1410             icvDestroyBackgroundReaders();
1411         }
1412         icvEndSampleDistortion( &data );
1413     }
1414 }
1415 
1416 
cvCreateTrainingSamplesFromInfo(const char * infoname,const char * vecfilename,int num,int showsamples,int winwidth,int winheight)1417 int cvCreateTrainingSamplesFromInfo( const char* infoname, const char* vecfilename,
1418                                      int num,
1419                                      int showsamples,
1420                                      int winwidth, int winheight )
1421 {
1422     char fullname[PATH_MAX];
1423     char* filename;
1424 
1425     FILE* info;
1426     FILE* vec;
1427     IplImage* src=0;
1428     IplImage* sample;
1429     int line;
1430     int error;
1431     int i;
1432     int x, y, width, height;
1433     int total;
1434 
1435     assert( infoname != NULL );
1436     assert( vecfilename != NULL );
1437 
1438     total = 0;
1439     if( !icvMkDir( vecfilename ) )
1440     {
1441 
1442 #if CV_VERBOSE
1443         fprintf( stderr, "Unable to create directory hierarchy: %s\n", vecfilename );
1444 #endif /* CV_VERBOSE */
1445 
1446         return total;
1447     }
1448 
1449     info = fopen( infoname, "r" );
1450     if( info == NULL )
1451     {
1452 
1453 #if CV_VERBOSE
1454         fprintf( stderr, "Unable to open file: %s\n", infoname );
1455 #endif /* CV_VERBOSE */
1456 
1457         return total;
1458     }
1459 
1460     vec = fopen( vecfilename, "wb" );
1461     if( vec == NULL )
1462     {
1463 
1464 #if CV_VERBOSE
1465         fprintf( stderr, "Unable to open file: %s\n", vecfilename );
1466 #endif /* CV_VERBOSE */
1467 
1468         fclose( info );
1469 
1470         return total;
1471     }
1472 
1473     sample = cvCreateImage( cvSize( winwidth, winheight ), IPL_DEPTH_8U, 1 );
1474 
1475     icvWriteVecHeader( vec, num, sample->width, sample->height );
1476 
1477     if( showsamples )
1478     {
1479         cvNamedWindow( "Sample", CV_WINDOW_AUTOSIZE );
1480     }
1481 
1482     strcpy( fullname, infoname );
1483     filename = strrchr( fullname, '\\' );
1484     if( filename == NULL )
1485     {
1486         filename = strrchr( fullname, '/' );
1487     }
1488     if( filename == NULL )
1489     {
1490         filename = fullname;
1491     }
1492     else
1493     {
1494         filename++;
1495     }
1496 
1497     for( line = 1, error = 0, total = 0; total < num ;line++ )
1498     {
1499         int count;
1500 
1501         error = ( fscanf( info, "%s %d", filename, &count ) != 2 );
1502         if( !error )
1503         {
1504             src = cvLoadImage( fullname, 0 );
1505             error = ( src == NULL );
1506             if( error )
1507             {
1508 
1509 #if CV_VERBOSE
1510                 fprintf( stderr, "Unable to open image: %s\n", fullname );
1511 #endif /* CV_VERBOSE */
1512 
1513             }
1514         }
1515         for( i = 0; (i < count) && (total < num); i++, total++ )
1516         {
1517             error = ( fscanf( info, "%d %d %d %d", &x, &y, &width, &height ) != 4 );
1518             if( error ) break;
1519             cvSetImageROI( src, cvRect( x, y, width, height ) );
1520             cvResize( src, sample, width >= sample->width &&
1521                       height >= sample->height ? CV_INTER_AREA : CV_INTER_LINEAR );
1522 
1523             if( showsamples )
1524             {
1525                 cvShowImage( "Sample", sample );
1526                 if( cvWaitKey( 0 ) == 27 )
1527                 {
1528                     showsamples = 0;
1529                 }
1530             }
1531             icvWriteVecSample( vec, sample );
1532         }
1533 
1534         if( src )
1535         {
1536             cvReleaseImage( &src );
1537         }
1538 
1539         if( error )
1540         {
1541 
1542 #if CV_VERBOSE
1543             fprintf( stderr, "%s(%d) : parse error", infoname, line );
1544 #endif /* CV_VERBOSE */
1545 
1546             break;
1547         }
1548     }
1549 
1550     if( sample )
1551     {
1552         cvReleaseImage( &sample );
1553     }
1554 
1555     fclose( vec );
1556     fclose( info );
1557 
1558     return total;
1559 }
1560 
1561 typedef struct CvVecFile
1562 {
1563     FILE*  input;
1564     int    count;
1565     int    vecsize;
1566     int    last;
1567     short* vector;
1568 } CvVecFile;
1569 
1570 static
icvGetTraininDataFromVec(CvMat * img,void * userdata)1571 int icvGetTraininDataFromVec( CvMat* img, void* userdata )
1572 {
1573     uchar tmp = 0;
1574     int r = 0;
1575     int c = 0;
1576 
1577     assert( img->rows * img->cols == ((CvVecFile*) userdata)->vecsize );
1578 
1579     size_t elements_read = fread( &tmp, sizeof( tmp ), 1, ((CvVecFile*) userdata)->input );
1580     CV_Assert(elements_read == 1);
1581     elements_read = fread( ((CvVecFile*) userdata)->vector, sizeof( short ),
1582            ((CvVecFile*) userdata)->vecsize, ((CvVecFile*) userdata)->input );
1583     CV_Assert(elements_read == (size_t)((CvVecFile*) userdata)->vecsize);
1584 
1585     if( feof( ((CvVecFile*) userdata)->input ) ||
1586         (((CvVecFile*) userdata)->last)++ >= ((CvVecFile*) userdata)->count )
1587     {
1588         return 0;
1589     }
1590 
1591     for( r = 0; r < img->rows; r++ )
1592     {
1593         for( c = 0; c < img->cols; c++ )
1594         {
1595             CV_MAT_ELEM( *img, uchar, r, c ) =
1596                 (uchar) ( ((CvVecFile*) userdata)->vector[r * img->cols + c] );
1597         }
1598     }
1599 
1600     return 1;
1601 }
cvShowVecSamples(const char * filename,int winwidth,int winheight,double scale)1602 void cvShowVecSamples( const char* filename, int winwidth, int winheight,
1603                        double scale )
1604 {
1605     CvVecFile file;
1606     short tmp;
1607     int i;
1608     CvMat* sample;
1609 
1610     tmp = 0;
1611     file.input = fopen( filename, "rb" );
1612 
1613     if( file.input != NULL )
1614     {
1615         size_t elements_read1 = fread( &file.count, sizeof( file.count ), 1, file.input );
1616         size_t elements_read2 = fread( &file.vecsize, sizeof( file.vecsize ), 1, file.input );
1617         size_t elements_read3 = fread( &tmp, sizeof( tmp ), 1, file.input );
1618         size_t elements_read4 = fread( &tmp, sizeof( tmp ), 1, file.input );
1619         CV_Assert(elements_read1 == 1 && elements_read2 == 1 && elements_read3 == 1 && elements_read4 == 1);
1620 
1621         if( file.vecsize != winwidth * winheight )
1622         {
1623             int guessed_w = 0;
1624             int guessed_h = 0;
1625 
1626             fprintf( stderr, "Warning: specified sample width=%d and height=%d "
1627                 "does not correspond to .vec file vector size=%d.\n",
1628                 winwidth, winheight, file.vecsize );
1629             if( file.vecsize > 0 )
1630             {
1631                 guessed_w = cvFloor( sqrt( (float) file.vecsize ) );
1632                 if( guessed_w > 0 )
1633                 {
1634                     guessed_h = file.vecsize / guessed_w;
1635                 }
1636             }
1637 
1638             if( guessed_w <= 0 || guessed_h <= 0 || guessed_w * guessed_h != file.vecsize)
1639             {
1640                 fprintf( stderr, "Error: failed to guess sample width and height\n" );
1641                 fclose( file.input );
1642 
1643                 return;
1644             }
1645             else
1646             {
1647                 winwidth = guessed_w;
1648                 winheight = guessed_h;
1649                 fprintf( stderr, "Guessed width=%d, guessed height=%d\n",
1650                     winwidth, winheight );
1651             }
1652         }
1653 
1654         if( !feof( file.input ) && scale > 0 )
1655         {
1656             CvMat* scaled_sample = 0;
1657 
1658             file.last = 0;
1659             file.vector = (short*) cvAlloc( sizeof( *file.vector ) * file.vecsize );
1660             sample = scaled_sample = cvCreateMat( winheight, winwidth, CV_8UC1 );
1661             if( scale != 1.0 )
1662             {
1663                 scaled_sample = cvCreateMat( MAX( 1, cvCeil( scale * winheight ) ),
1664                                              MAX( 1, cvCeil( scale * winwidth ) ),
1665                                              CV_8UC1 );
1666             }
1667             cvNamedWindow( "Sample", CV_WINDOW_AUTOSIZE );
1668             for( i = 0; i < file.count; i++ )
1669             {
1670                 icvGetTraininDataFromVec( sample, &file );
1671                 if( scale != 1.0 ) cvResize( sample, scaled_sample, CV_INTER_LINEAR);
1672                 cvShowImage( "Sample", scaled_sample );
1673                 if( cvWaitKey( 0 ) == 27 ) break;
1674             }
1675             if( scaled_sample && scaled_sample != sample ) cvReleaseMat( &scaled_sample );
1676             cvReleaseMat( &sample );
1677             cvFree( &file.vector );
1678         }
1679         fclose( file.input );
1680     }
1681 }