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 }