Home | History | Annotate | Download | only in createsamples
      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 
     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 
    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 
    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  */
    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 */
    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
    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 
    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
    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
    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
    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
    926 void icvReleaseBackgroundData( CvBackgroundData** data )
    927 {
    928     assert( data != NULL && (*data) != NULL );
    929 
    930     cvFree( data );
    931 }
    932 
    933 static
    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
    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
    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
   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  */
   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
   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 
   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 
   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 
   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
   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 }
   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 }