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 }