cveigenobjects.cpp revision 6acb9a7ea3d7564944e12cbc73a857b88c1301ee
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 "_cvaux.h" 43 44CvStatus CV_STDCALL 45icvJacobiEigens_32f(float *A, float *V, float *E, int n, float eps) 46{ 47 int i, j, k, ind; 48 float *AA = A, *VV = V; 49 double Amax, anorm = 0, ax; 50 51 if( A == NULL || V == NULL || E == NULL ) 52 return CV_NULLPTR_ERR; 53 if( n <= 0 ) 54 return CV_BADSIZE_ERR; 55 if( eps < 1.0e-7f ) 56 eps = 1.0e-7f; 57 58 /*-------- Prepare --------*/ 59 for( i = 0; i < n; i++, VV += n, AA += n ) 60 { 61 for( j = 0; j < i; j++ ) 62 { 63 double Am = AA[j]; 64 65 anorm += Am * Am; 66 } 67 for( j = 0; j < n; j++ ) 68 VV[j] = 0.f; 69 VV[i] = 1.f; 70 } 71 72 anorm = sqrt( anorm + anorm ); 73 ax = anorm * eps / n; 74 Amax = anorm; 75 76 while( Amax > ax ) 77 { 78 Amax /= n; 79 do /* while (ind) */ 80 { 81 int p, q; 82 float *V1 = V, *A1 = A; 83 84 ind = 0; 85 for( p = 0; p < n - 1; p++, A1 += n, V1 += n ) 86 { 87 float *A2 = A + n * (p + 1), *V2 = V + n * (p + 1); 88 89 for( q = p + 1; q < n; q++, A2 += n, V2 += n ) 90 { 91 double x, y, c, s, c2, s2, a; 92 float *A3, Apq = A1[q], App, Aqq, Aip, Aiq, Vpi, Vqi; 93 94 if( fabs( Apq ) < Amax ) 95 continue; 96 97 ind = 1; 98 99 /*---- Calculation of rotation angle's sine & cosine ----*/ 100 App = A1[p]; 101 Aqq = A2[q]; 102 y = 5.0e-1 * (App - Aqq); 103 x = -Apq / sqrt( (double)Apq * Apq + (double)y * y ); 104 if( y < 0.0 ) 105 x = -x; 106 s = x / sqrt( 2.0 * (1.0 + sqrt( 1.0 - (double)x * x ))); 107 s2 = s * s; 108 c = sqrt( 1.0 - s2 ); 109 c2 = c * c; 110 a = 2.0 * Apq * c * s; 111 112 /*---- Apq annulation ----*/ 113 A3 = A; 114 for( i = 0; i < p; i++, A3 += n ) 115 { 116 Aip = A3[p]; 117 Aiq = A3[q]; 118 Vpi = V1[i]; 119 Vqi = V2[i]; 120 A3[p] = (float) (Aip * c - Aiq * s); 121 A3[q] = (float) (Aiq * c + Aip * s); 122 V1[i] = (float) (Vpi * c - Vqi * s); 123 V2[i] = (float) (Vqi * c + Vpi * s); 124 } 125 for( ; i < q; i++, A3 += n ) 126 { 127 Aip = A1[i]; 128 Aiq = A3[q]; 129 Vpi = V1[i]; 130 Vqi = V2[i]; 131 A1[i] = (float) (Aip * c - Aiq * s); 132 A3[q] = (float) (Aiq * c + Aip * s); 133 V1[i] = (float) (Vpi * c - Vqi * s); 134 V2[i] = (float) (Vqi * c + Vpi * s); 135 } 136 for( ; i < n; i++ ) 137 { 138 Aip = A1[i]; 139 Aiq = A2[i]; 140 Vpi = V1[i]; 141 Vqi = V2[i]; 142 A1[i] = (float) (Aip * c - Aiq * s); 143 A2[i] = (float) (Aiq * c + Aip * s); 144 V1[i] = (float) (Vpi * c - Vqi * s); 145 V2[i] = (float) (Vqi * c + Vpi * s); 146 } 147 A1[p] = (float) (App * c2 + Aqq * s2 - a); 148 A2[q] = (float) (App * s2 + Aqq * c2 + a); 149 A1[q] = A2[p] = 0.0f; 150 } /*q */ 151 } /*p */ 152 } 153 while( ind ); 154 Amax /= n; 155 } /* while ( Amax > ax ) */ 156 157 for( i = 0, k = 0; i < n; i++, k += n + 1 ) 158 E[i] = A[k]; 159 /*printf(" M = %d\n", M); */ 160 161 /* -------- ordering -------- */ 162 for( i = 0; i < n; i++ ) 163 { 164 int m = i; 165 float Em = (float) fabs( E[i] ); 166 167 for( j = i + 1; j < n; j++ ) 168 { 169 float Ej = (float) fabs( E[j] ); 170 171 m = (Em < Ej) ? j : m; 172 Em = (Em < Ej) ? Ej : Em; 173 } 174 if( m != i ) 175 { 176 int l; 177 float b = E[i]; 178 179 E[i] = E[m]; 180 E[m] = b; 181 for( j = 0, k = i * n, l = m * n; j < n; j++, k++, l++ ) 182 { 183 b = V[k]; 184 V[k] = V[l]; 185 V[l] = b; 186 } 187 } 188 } 189 190 return CV_NO_ERR; 191} 192 193/*F/////////////////////////////////////////////////////////////////////////////////////// 194// Name: icvCalcCovarMatrixEx_8u32fR 195// Purpose: The function calculates a covariance matrix for a group of input objects 196// (images, vectors, etc.). ROI supported. 197// Context: 198// Parameters: nObjects - number of source objects 199// objects - array of pointers to ROIs of the source objects 200// imgStep - full width of each source object row in bytes 201// avg - pointer to averaged object 202// avgStep - full width of averaged object row in bytes 203// size - ROI size of each source and averaged objects 204// covarMatrix - covariance matrix (output parameter; must be allocated 205// before call) 206// 207// Returns: CV_NO_ERR or error code 208// 209// Notes: 210//F*/ 211static CvStatus CV_STDCALL 212icvCalcCovarMatrixEx_8u32fR( int nObjects, void *input, int objStep1, 213 int ioFlags, int ioBufSize, uchar* buffer, 214 void *userData, float *avg, int avgStep, 215 CvSize size, float *covarMatrix ) 216{ 217 int objStep = objStep1; 218 219 /* ---- TEST OF PARAMETERS ---- */ 220 221 if( nObjects < 2 ) 222 return CV_BADFACTOR_ERR; 223 if( ioFlags < 0 || ioFlags > 3 ) 224 return CV_BADFACTOR_ERR; 225 if( ioFlags && ioBufSize < 1024 ) 226 return CV_BADFACTOR_ERR; 227 if( ioFlags && buffer == NULL ) 228 return CV_NULLPTR_ERR; 229 if( input == NULL || avg == NULL || covarMatrix == NULL ) 230 return CV_NULLPTR_ERR; 231 if( size.width > objStep || 4 * size.width > avgStep || size.height < 1 ) 232 return CV_BADSIZE_ERR; 233 234 avgStep /= 4; 235 236 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK ) /* ==== USE INPUT CALLBACK ==== */ 237 { 238 int nio, ngr, igr, n = size.width * size.height, mm = 0; 239 CvCallback read_callback = ((CvInput *) & input)->callback; 240 uchar *buffer2; 241 242 objStep = n; 243 nio = ioBufSize / n; /* number of objects in buffer */ 244 ngr = nObjects / nio; /* number of io groups */ 245 if( nObjects % nio ) 246 mm = 1; 247 ngr += mm; 248 249 buffer2 = (uchar *)cvAlloc( sizeof( uchar ) * n ); 250 if( buffer2 == NULL ) 251 return CV_OUTOFMEM_ERR; 252 253 for( igr = 0; igr < ngr; igr++ ) 254 { 255 int k, l; 256 int io, jo, imin = igr * nio, imax = imin + nio; 257 uchar *bu1 = buffer, *bu2; 258 259 if( imax > nObjects ) 260 imax = nObjects; 261 262 /* read igr group */ 263 for( io = imin; io < imax; io++, bu1 += n ) 264 { 265 CvStatus r; 266 267 r = (CvStatus)read_callback( io, (void *) bu1, userData ); 268 if( r ) 269 return r; 270 } 271 272 /* diagonal square calc */ 273 bu1 = buffer; 274 for( io = imin; io < imax; io++, bu1 += n ) 275 { 276 bu2 = bu1; 277 for( jo = io; jo < imax; jo++, bu2 += n ) 278 { 279 float w = 0.f; 280 float *fu = avg; 281 int ij = 0; 282 283 for( k = 0; k < size.height; k++, fu += avgStep ) 284 for( l = 0; l < size.width; l++, ij++ ) 285 { 286 float f = fu[l], u1 = bu1[ij], u2 = bu2[ij]; 287 288 w += (u1 - f) * (u2 - f); 289 } 290 covarMatrix[io * nObjects + jo] = covarMatrix[jo * nObjects + io] = w; 291 } 292 } 293 294 /* non-diagonal elements calc */ 295 for( jo = imax; jo < nObjects; jo++ ) 296 { 297 CvStatus r; 298 299 bu1 = buffer; 300 bu2 = buffer2; 301 302 /* read jo object */ 303 r = (CvStatus)read_callback( jo, (void *) bu2, userData ); 304 if( r ) 305 return r; 306 307 for( io = imin; io < imax; io++, bu1 += n ) 308 { 309 float w = 0.f; 310 float *fu = avg; 311 int ij = 0; 312 313 for( k = 0; k < size.height; k++, fu += avgStep ) 314 { 315 for( l = 0; l < size.width - 3; l += 4, ij += 4 ) 316 { 317 float f = fu[l]; 318 uchar u1 = bu1[ij]; 319 uchar u2 = bu2[ij]; 320 321 w += (u1 - f) * (u2 - f); 322 f = fu[l + 1]; 323 u1 = bu1[ij + 1]; 324 u2 = bu2[ij + 1]; 325 w += (u1 - f) * (u2 - f); 326 f = fu[l + 2]; 327 u1 = bu1[ij + 2]; 328 u2 = bu2[ij + 2]; 329 w += (u1 - f) * (u2 - f); 330 f = fu[l + 3]; 331 u1 = bu1[ij + 3]; 332 u2 = bu2[ij + 3]; 333 w += (u1 - f) * (u2 - f); 334 } 335 for( ; l < size.width; l++, ij++ ) 336 { 337 float f = fu[l], u1 = bu1[ij], u2 = bu2[ij]; 338 339 w += (u1 - f) * (u2 - f); 340 } 341 } 342 covarMatrix[io * nObjects + jo] = covarMatrix[jo * nObjects + io] = w; 343 } 344 } 345 } /* igr */ 346 347 cvFree( &buffer2 ); 348 } /* if() */ 349 350 else 351 /* ==== NOT USE INPUT CALLBACK ==== */ 352 { 353 int i, j; 354 uchar **objects = (uchar **) (((CvInput *) & input)->data); 355 356 for( i = 0; i < nObjects; i++ ) 357 { 358 uchar *bu = objects[i]; 359 360 for( j = i; j < nObjects; j++ ) 361 { 362 int k, l; 363 float w = 0.f; 364 float *a = avg; 365 uchar *bu1 = bu; 366 uchar *bu2 = objects[j]; 367 368 for( k = 0; k < size.height; 369 k++, bu1 += objStep, bu2 += objStep, a += avgStep ) 370 { 371 for( l = 0; l < size.width - 3; l += 4 ) 372 { 373 float f = a[l]; 374 uchar u1 = bu1[l]; 375 uchar u2 = bu2[l]; 376 377 w += (u1 - f) * (u2 - f); 378 f = a[l + 1]; 379 u1 = bu1[l + 1]; 380 u2 = bu2[l + 1]; 381 w += (u1 - f) * (u2 - f); 382 f = a[l + 2]; 383 u1 = bu1[l + 2]; 384 u2 = bu2[l + 2]; 385 w += (u1 - f) * (u2 - f); 386 f = a[l + 3]; 387 u1 = bu1[l + 3]; 388 u2 = bu2[l + 3]; 389 w += (u1 - f) * (u2 - f); 390 } 391 for( ; l < size.width; l++ ) 392 { 393 float f = a[l]; 394 uchar u1 = bu1[l]; 395 uchar u2 = bu2[l]; 396 397 w += (u1 - f) * (u2 - f); 398 } 399 } 400 401 covarMatrix[i * nObjects + j] = covarMatrix[j * nObjects + i] = w; 402 } 403 } 404 } /* else */ 405 406 return CV_NO_ERR; 407} 408 409/*======================== end of icvCalcCovarMatrixEx_8u32fR ===========================*/ 410 411 412static int 413icvDefaultBufferSize( void ) 414{ 415 return 10 * 1024 * 1024; 416} 417 418/*F/////////////////////////////////////////////////////////////////////////////////////// 419// Name: icvCalcEigenObjects_8u32fR 420// Purpose: The function calculates an orthonormal eigen basis and a mean (averaged) 421// object for a group of input objects (images, vectors, etc.). ROI supported. 422// Context: 423// Parameters: nObjects - number of source objects 424// input - pointer either to array of pointers to input objects 425// or to read callback function (depending on ioFlags) 426// imgStep - full width of each source object row in bytes 427// output - pointer either to array of pointers to output eigen objects 428// or to write callback function (depending on ioFlags) 429// eigStep - full width of each eigenobject row in bytes 430// size - ROI size of each source object 431// ioFlags - input/output flags (see Notes) 432// ioBufSize - input/output buffer size 433// userData - pointer to the structure which contains all necessary 434// data for the callback functions 435// calcLimit - determines the calculation finish conditions 436// avg - pointer to averaged object (has the same size as ROI) 437// avgStep - full width of averaged object row in bytes 438// eigVals - pointer to corresponding eigenvalues (array of <nObjects> 439// elements in descending order) 440// 441// Returns: CV_NO_ERR or error code 442// 443// Notes: 1. input/output data (that is, input objects and eigen ones) may either 444// be allocated in the RAM or be read from/written to the HDD (or any 445// other device) by read/write callback functions. It depends on the 446// value of ioFlags paramater, which may be the following: 447// CV_EIGOBJ_NO_CALLBACK, or 0; 448// CV_EIGOBJ_INPUT_CALLBACK; 449// CV_EIGOBJ_OUTPUT_CALLBACK; 450// CV_EIGOBJ_BOTH_CALLBACK, or 451// CV_EIGOBJ_INPUT_CALLBACK | CV_EIGOBJ_OUTPUT_CALLBACK. 452// The callback functions as well as the user data structure must be 453// developed by the user. 454// 455// 2. If ioBufSize = 0, or it's too large, the function dermines buffer size 456// itself. 457// 458// 3. Depending on calcLimit parameter, calculations are finished either if 459// eigenfaces number comes up to certain value or the relation of the 460// current eigenvalue and the largest one comes down to certain value 461// (or any of the above conditions takes place). The calcLimit->type value 462// must be CV_TERMCRIT_NUMB, CV_TERMCRIT_EPS or 463// CV_TERMCRIT_NUMB | CV_TERMCRIT_EPS. The function returns the real 464// values calcLimit->max_iter and calcLimit->epsilon. 465// 466// 4. eigVals may be equal to NULL (if you don't need eigen values in further). 467// 468//F*/ 469static CvStatus CV_STDCALL 470icvCalcEigenObjects_8u32fR( int nObjects, void* input, int objStep, 471 void* output, int eigStep, CvSize size, 472 int ioFlags, int ioBufSize, void* userData, 473 CvTermCriteria* calcLimit, float* avg, 474 int avgStep, float *eigVals ) 475{ 476 int i, j, n, iev = 0, m1 = nObjects - 1, objStep1 = objStep, eigStep1 = eigStep / 4; 477 CvSize objSize, eigSize, avgSize; 478 float *c = 0; 479 float *ev = 0; 480 float *bf = 0; 481 uchar *buf = 0; 482 void *buffer = 0; 483 float m = 1.0f / (float) nObjects; 484 CvStatus r; 485 486 if( m1 > calcLimit->max_iter && calcLimit->type != CV_TERMCRIT_EPS ) 487 m1 = calcLimit->max_iter; 488 489 /* ---- TEST OF PARAMETERS ---- */ 490 491 if( nObjects < 2 ) 492 return CV_BADFACTOR_ERR; 493 if( ioFlags < 0 || ioFlags > 3 ) 494 return CV_BADFACTOR_ERR; 495 if( input == NULL || output == NULL || avg == NULL ) 496 return CV_NULLPTR_ERR; 497 if( size.width > objStep || 4 * size.width > eigStep || 498 4 * size.width > avgStep || size.height < 1 ) 499 return CV_BADSIZE_ERR; 500 if( !(ioFlags & CV_EIGOBJ_INPUT_CALLBACK) ) 501 for( i = 0; i < nObjects; i++ ) 502 if( ((uchar **) input)[i] == NULL ) 503 return CV_NULLPTR_ERR; 504 if( !(ioFlags & CV_EIGOBJ_OUTPUT_CALLBACK) ) 505 for( i = 0; i < m1; i++ ) 506 if( ((float **) output)[i] == NULL ) 507 return CV_NULLPTR_ERR; 508 509 avgStep /= 4; 510 eigStep /= 4; 511 512 if( objStep == size.width && eigStep == size.width && avgStep == size.width ) 513 { 514 size.width *= size.height; 515 size.height = 1; 516 objStep = objStep1 = eigStep = eigStep1 = avgStep = size.width; 517 } 518 objSize = eigSize = avgSize = size; 519 520 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK ) 521 { 522 objSize.width *= objSize.height; 523 objSize.height = 1; 524 objStep = objSize.width; 525 objStep1 = size.width; 526 } 527 528 if( ioFlags & CV_EIGOBJ_OUTPUT_CALLBACK ) 529 { 530 eigSize.width *= eigSize.height; 531 eigSize.height = 1; 532 eigStep = eigSize.width; 533 eigStep1 = size.width; 534 } 535 536 n = objSize.height * objSize.width * (ioFlags & CV_EIGOBJ_INPUT_CALLBACK) + 537 2 * eigSize.height * eigSize.width * (ioFlags & CV_EIGOBJ_OUTPUT_CALLBACK); 538 539 /* Buffer size determination */ 540 if( ioFlags ) 541 { 542 int size = icvDefaultBufferSize(); 543 ioBufSize = MIN( size, n ); 544 } 545 546 /* memory allocation (if necesseay) */ 547 548 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK ) 549 { 550 buf = (uchar *) cvAlloc( sizeof( uchar ) * objSize.width ); 551 if( buf == NULL ) 552 return CV_OUTOFMEM_ERR; 553 } 554 555 if( ioFlags ) 556 { 557 buffer = (void *) cvAlloc( ioBufSize ); 558 if( buffer == NULL ) 559 { 560 if( buf ) 561 cvFree( &buf ); 562 return CV_OUTOFMEM_ERR; 563 } 564 } 565 566 /* Calculation of averaged object */ 567 bf = avg; 568 for( i = 0; i < avgSize.height; i++, bf += avgStep ) 569 for( j = 0; j < avgSize.width; j++ ) 570 bf[j] = 0.f; 571 572 for( i = 0; i < nObjects; i++ ) 573 { 574 int k, l; 575 uchar *bu = (ioFlags & CV_EIGOBJ_INPUT_CALLBACK) ? buf : ((uchar **) input)[i]; 576 577 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK ) 578 { 579 CvCallback read_callback = ((CvInput *) & input)->callback; 580 581 r = (CvStatus)read_callback( i, (void *) buf, userData ); 582 if( r ) 583 { 584 if( buffer ) 585 cvFree( &buffer ); 586 if( buf ) 587 cvFree( &buf ); 588 return r; 589 } 590 } 591 592 bf = avg; 593 for( k = 0; k < avgSize.height; k++, bf += avgStep, bu += objStep1 ) 594 for( l = 0; l < avgSize.width; l++ ) 595 bf[l] += bu[l]; 596 } 597 598 bf = avg; 599 for( i = 0; i < avgSize.height; i++, bf += avgStep ) 600 for( j = 0; j < avgSize.width; j++ ) 601 bf[j] *= m; 602 603 /* Calculation of covariance matrix */ 604 c = (float *) cvAlloc( sizeof( float ) * nObjects * nObjects ); 605 606 if( c == NULL ) 607 { 608 if( buffer ) 609 cvFree( &buffer ); 610 if( buf ) 611 cvFree( &buf ); 612 return CV_OUTOFMEM_ERR; 613 } 614 615 r = icvCalcCovarMatrixEx_8u32fR( nObjects, input, objStep1, ioFlags, ioBufSize, 616 (uchar *) buffer, userData, avg, 4 * avgStep, size, c ); 617 if( r ) 618 { 619 cvFree( &c ); 620 if( buffer ) 621 cvFree( &buffer ); 622 if( buf ) 623 cvFree( &buf ); 624 return r; 625 } 626 627 /* Calculation of eigenvalues & eigenvectors */ 628 ev = (float *) cvAlloc( sizeof( float ) * nObjects * nObjects ); 629 630 if( ev == NULL ) 631 { 632 cvFree( &c ); 633 if( buffer ) 634 cvFree( &buffer ); 635 if( buf ) 636 cvFree( &buf ); 637 return CV_OUTOFMEM_ERR; 638 } 639 640 if( eigVals == NULL ) 641 { 642 eigVals = (float *) cvAlloc( sizeof( float ) * nObjects ); 643 644 if( eigVals == NULL ) 645 { 646 cvFree( &c ); 647 cvFree( &ev ); 648 if( buffer ) 649 cvFree( &buffer ); 650 if( buf ) 651 cvFree( &buf ); 652 return CV_OUTOFMEM_ERR; 653 } 654 iev = 1; 655 } 656 657 r = icvJacobiEigens_32f( c, ev, eigVals, nObjects, 0.0f ); 658 cvFree( &c ); 659 if( r ) 660 { 661 cvFree( &ev ); 662 if( buffer ) 663 cvFree( &buffer ); 664 if( buf ) 665 cvFree( &buf ); 666 if( iev ) 667 cvFree( &eigVals ); 668 return r; 669 } 670 671 /* Eigen objects number determination */ 672 if( calcLimit->type != CV_TERMCRIT_NUMBER ) 673 { 674 for( i = 0; i < m1; i++ ) 675 if( fabs( eigVals[i] / eigVals[0] ) < calcLimit->epsilon ) 676 break; 677 m1 = calcLimit->max_iter = i; 678 } 679 else 680 m1 = calcLimit->max_iter; 681 calcLimit->epsilon = (float) fabs( eigVals[m1 - 1] / eigVals[0] ); 682 683 for( i = 0; i < m1; i++ ) 684 eigVals[i] = (float) (1.0 / sqrt( (double)eigVals[i] )); 685 686 /* ----------------- Calculation of eigenobjects ----------------------- */ 687 if( ioFlags & CV_EIGOBJ_OUTPUT_CALLBACK ) 688 { 689 int nio, ngr, igr; 690 691 nio = ioBufSize / (4 * eigSize.width); /* number of eigen objects in buffer */ 692 ngr = m1 / nio; /* number of io groups */ 693 if( nObjects % nio ) 694 ngr += 1; 695 696 for( igr = 0; igr < ngr; igr++ ) 697 { 698 int i, io, ie, imin = igr * nio, imax = imin + nio; 699 700 if( imax > m1 ) 701 imax = m1; 702 703 for( i = 0; i < eigSize.width * (imax - imin); i++ ) 704 ((float *) buffer)[i] = 0.f; 705 706 for( io = 0; io < nObjects; io++ ) 707 { 708 uchar *bu = ioFlags & CV_EIGOBJ_INPUT_CALLBACK ? buf : ((uchar **) input)[io]; 709 710 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK ) 711 { 712 CvCallback read_callback = ((CvInput *) & input)->callback; 713 714 r = (CvStatus)read_callback( io, (void *) buf, userData ); 715 if( r ) 716 { 717 cvFree( &ev ); 718 if( iev ) 719 cvFree( &eigVals ); 720 if( buffer ) 721 cvFree( &buffer ); 722 if( buf ) 723 cvFree( &buf ); 724 return r; 725 } 726 } 727 728 for( ie = imin; ie < imax; ie++ ) 729 { 730 int k, l; 731 uchar *bv = bu; 732 float e = ev[ie * nObjects + io] * eigVals[ie]; 733 float *be = ((float *) buffer) + ((ie - imin) * eigStep); 734 735 bf = avg; 736 for( k = 0; k < size.height; k++, bv += objStep1, 737 bf += avgStep, be += eigStep1 ) 738 { 739 for( l = 0; l < size.width - 3; l += 4 ) 740 { 741 float f = bf[l]; 742 uchar v = bv[l]; 743 744 be[l] += e * (v - f); 745 f = bf[l + 1]; 746 v = bv[l + 1]; 747 be[l + 1] += e * (v - f); 748 f = bf[l + 2]; 749 v = bv[l + 2]; 750 be[l + 2] += e * (v - f); 751 f = bf[l + 3]; 752 v = bv[l + 3]; 753 be[l + 3] += e * (v - f); 754 } 755 for( ; l < size.width; l++ ) 756 be[l] += e * (bv[l] - bf[l]); 757 } 758 } 759 } /* io */ 760 761 for( ie = imin; ie < imax; ie++ ) /* calculated eigen objects writting */ 762 { 763 CvCallback write_callback = ((CvInput *) & output)->callback; 764 float *be = ((float *) buffer) + ((ie - imin) * eigStep); 765 766 r = (CvStatus)write_callback( ie, (void *) be, userData ); 767 if( r ) 768 { 769 cvFree( &ev ); 770 if( iev ) 771 cvFree( &eigVals ); 772 if( buffer ) 773 cvFree( &buffer ); 774 if( buf ) 775 cvFree( &buf ); 776 return r; 777 } 778 } 779 } /* igr */ 780 } 781 782 else 783 { 784 int k, p, l; 785 786 for( i = 0; i < m1; i++ ) /* e.o. annulation */ 787 { 788 float *be = ((float **) output)[i]; 789 790 for( p = 0; p < eigSize.height; p++, be += eigStep ) 791 for( l = 0; l < eigSize.width; l++ ) 792 be[l] = 0.0f; 793 } 794 795 for( k = 0; k < nObjects; k++ ) 796 { 797 uchar *bv = (ioFlags & CV_EIGOBJ_INPUT_CALLBACK) ? buf : ((uchar **) input)[k]; 798 799 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK ) 800 { 801 CvCallback read_callback = ((CvInput *) & input)->callback; 802 803 r = (CvStatus)read_callback( k, (void *) buf, userData ); 804 if( r ) 805 { 806 cvFree( &ev ); 807 if( iev ) 808 cvFree( &eigVals ); 809 if( buffer ) 810 cvFree( &buffer ); 811 if( buf ) 812 cvFree( &buf ); 813 return r; 814 } 815 } 816 817 for( i = 0; i < m1; i++ ) 818 { 819 float v = eigVals[i] * ev[i * nObjects + k]; 820 float *be = ((float **) output)[i]; 821 uchar *bu = bv; 822 823 bf = avg; 824 825 for( p = 0; p < size.height; p++, bu += objStep1, 826 bf += avgStep, be += eigStep1 ) 827 { 828 for( l = 0; l < size.width - 3; l += 4 ) 829 { 830 float f = bf[l]; 831 uchar u = bu[l]; 832 833 be[l] += v * (u - f); 834 f = bf[l + 1]; 835 u = bu[l + 1]; 836 be[l + 1] += v * (u - f); 837 f = bf[l + 2]; 838 u = bu[l + 2]; 839 be[l + 2] += v * (u - f); 840 f = bf[l + 3]; 841 u = bu[l + 3]; 842 be[l + 3] += v * (u - f); 843 } 844 for( ; l < size.width; l++ ) 845 be[l] += v * (bu[l] - bf[l]); 846 } 847 } /* i */ 848 } /* k */ 849 } /* else */ 850 851 cvFree( &ev ); 852 if( iev ) 853 cvFree( &eigVals ); 854 else 855 for( i = 0; i < m1; i++ ) 856 eigVals[i] = 1.f / (eigVals[i] * eigVals[i]); 857 if( buffer ) 858 cvFree( &buffer ); 859 if( buf ) 860 cvFree( &buf ); 861 return CV_NO_ERR; 862} 863 864/* --- End of icvCalcEigenObjects_8u32fR --- */ 865 866/*F/////////////////////////////////////////////////////////////////////////////////////// 867// Name: icvCalcDecompCoeff_8u32fR 868// Purpose: The function calculates one decomposition coefficient of input object 869// using previously calculated eigen object and the mean (averaged) object 870// Context: 871// Parameters: obj - input object 872// objStep - its step (in bytes) 873// eigObj - pointer to eigen object 874// eigStep - its step (in bytes) 875// avg - pointer to averaged object 876// avgStep - its step (in bytes) 877// size - ROI size of each source object 878// 879// Returns: decomposition coefficient value or large negative value (if error) 880// 881// Notes: 882//F*/ 883static float CV_STDCALL 884icvCalcDecompCoeff_8u32fR( uchar* obj, int objStep, 885 float *eigObj, int eigStep, 886 float *avg, int avgStep, CvSize size ) 887{ 888 int i, k; 889 float w = 0.0f; 890 891 if( size.width > objStep || 4 * size.width > eigStep 892 || 4 * size.width > avgStep || size.height < 1 ) 893 return -1.0e30f; 894 if( obj == NULL || eigObj == NULL || avg == NULL ) 895 return -1.0e30f; 896 897 eigStep /= 4; 898 avgStep /= 4; 899 900 if( size.width == objStep && size.width == eigStep && size.width == avgStep ) 901 { 902 size.width *= size.height; 903 size.height = 1; 904 objStep = eigStep = avgStep = size.width; 905 } 906 907 for( i = 0; i < size.height; i++, obj += objStep, eigObj += eigStep, avg += avgStep ) 908 { 909 for( k = 0; k < size.width - 4; k += 4 ) 910 { 911 float o = (float) obj[k]; 912 float e = eigObj[k]; 913 float a = avg[k]; 914 915 w += e * (o - a); 916 o = (float) obj[k + 1]; 917 e = eigObj[k + 1]; 918 a = avg[k + 1]; 919 w += e * (o - a); 920 o = (float) obj[k + 2]; 921 e = eigObj[k + 2]; 922 a = avg[k + 2]; 923 w += e * (o - a); 924 o = (float) obj[k + 3]; 925 e = eigObj[k + 3]; 926 a = avg[k + 3]; 927 w += e * (o - a); 928 } 929 for( ; k < size.width; k++ ) 930 w += eigObj[k] * ((float) obj[k] - avg[k]); 931 } 932 933 return w; 934} 935 936/*F/////////////////////////////////////////////////////////////////////////////////////// 937// Names: icvEigenDecomposite_8u32fR 938// Purpose: The function calculates all decomposition coefficients for input object 939// using previously calculated eigen objects basis and the mean (averaged) 940// object 941// Context: 942// Parameters: obj - input object 943// objStep - its step (in bytes) 944// nEigObjs - number of eigen objects 945// eigInput - pointer either to array of pointers to eigen objects 946// or to read callback function (depending on ioFlags) 947// eigStep - eigen objects step (in bytes) 948// ioFlags - input/output flags 949// iserData - pointer to the structure which contains all necessary 950// data for the callback function 951// avg - pointer to averaged object 952// avgStep - its step (in bytes) 953// size - ROI size of each source object 954// coeffs - calculated coefficients (output data) 955// 956// Returns: icv status 957// 958// Notes: see notes for icvCalcEigenObjects_8u32fR function 959//F*/ 960static CvStatus CV_STDCALL 961icvEigenDecomposite_8u32fR( uchar * obj, int objStep, int nEigObjs, 962 void *eigInput, int eigStep, int ioFlags, 963 void *userData, float *avg, int avgStep, 964 CvSize size, float *coeffs ) 965{ 966 int i; 967 968 if( nEigObjs < 2 ) 969 return CV_BADFACTOR_ERR; 970 if( ioFlags < 0 || ioFlags > 1 ) 971 return CV_BADFACTOR_ERR; 972 if( size.width > objStep || 4 * size.width > eigStep || 973 4 * size.width > avgStep || size.height < 1 ) 974 return CV_BADSIZE_ERR; 975 if( obj == NULL || eigInput == NULL || coeffs == NULL || avg == NULL ) 976 return CV_NULLPTR_ERR; 977 if( !ioFlags ) 978 for( i = 0; i < nEigObjs; i++ ) 979 if( ((uchar **) eigInput)[i] == NULL ) 980 return CV_NULLPTR_ERR; 981 982 if( ioFlags ) /* callback */ 983 984 { 985 float *buffer; 986 CvCallback read_callback = ((CvInput *) & eigInput)->callback; 987 988 eigStep = 4 * size.width; 989 990 /* memory allocation */ 991 buffer = (float *) cvAlloc( sizeof( float ) * size.width * size.height ); 992 993 if( buffer == NULL ) 994 return CV_OUTOFMEM_ERR; 995 996 for( i = 0; i < nEigObjs; i++ ) 997 { 998 float w; 999 CvStatus r = (CvStatus)read_callback( i, (void *) buffer, userData ); 1000 1001 if( r ) 1002 { 1003 cvFree( &buffer ); 1004 return r; 1005 } 1006 w = icvCalcDecompCoeff_8u32fR( obj, objStep, buffer, 1007 eigStep, avg, avgStep, size ); 1008 if( w < -1.0e29f ) 1009 { 1010 cvFree( &buffer ); 1011 return CV_NOTDEFINED_ERR; 1012 } 1013 coeffs[i] = w; 1014 } 1015 cvFree( &buffer ); 1016 } 1017 1018 else 1019 /* no callback */ 1020 for( i = 0; i < nEigObjs; i++ ) 1021 { 1022 float w = icvCalcDecompCoeff_8u32fR( obj, objStep, ((float **) eigInput)[i], 1023 eigStep, avg, avgStep, size ); 1024 1025 if( w < -1.0e29f ) 1026 return CV_NOTDEFINED_ERR; 1027 coeffs[i] = w; 1028 } 1029 1030 return CV_NO_ERR; 1031} 1032 1033 1034/*F/////////////////////////////////////////////////////////////////////////////////////// 1035// Names: icvEigenProjection_8u32fR 1036// Purpose: The function calculates object projection to the eigen sub-space (restores 1037// an object) using previously calculated eigen objects basis, mean (averaged) 1038// object and decomposition coefficients of the restored object 1039// Context: 1040// Parameters: nEigObjs - Number of eigen objects 1041// eigens - Array of pointers to eigen objects 1042// eigStep - Eigen objects step (in bytes) 1043// coeffs - Previously calculated decomposition coefficients 1044// avg - Pointer to averaged object 1045// avgStep - Its step (in bytes) 1046// rest - Pointer to restored object 1047// restStep - Its step (in bytes) 1048// size - ROI size of each object 1049// 1050// Returns: CV status 1051// 1052// Notes: 1053//F*/ 1054static CvStatus CV_STDCALL 1055icvEigenProjection_8u32fR( int nEigObjs, void *eigInput, int eigStep, 1056 int ioFlags, void *userData, float *coeffs, 1057 float *avg, int avgStep, uchar * rest, 1058 int restStep, CvSize size ) 1059{ 1060 int i, j, k; 1061 float *buf; 1062 float *buffer = NULL; 1063 float *b; 1064 CvCallback read_callback = ((CvInput *) & eigInput)->callback; 1065 1066 if( size.width > avgStep || 4 * size.width > eigStep || size.height < 1 ) 1067 return CV_BADSIZE_ERR; 1068 if( rest == NULL || eigInput == NULL || avg == NULL || coeffs == NULL ) 1069 return CV_NULLPTR_ERR; 1070 if( ioFlags < 0 || ioFlags > 1 ) 1071 return CV_BADFACTOR_ERR; 1072 if( !ioFlags ) 1073 for( i = 0; i < nEigObjs; i++ ) 1074 if( ((uchar **) eigInput)[i] == NULL ) 1075 return CV_NULLPTR_ERR; 1076 eigStep /= 4; 1077 avgStep /= 4; 1078 1079 if( size.width == restStep && size.width == eigStep && size.width == avgStep ) 1080 { 1081 size.width *= size.height; 1082 size.height = 1; 1083 restStep = eigStep = avgStep = size.width; 1084 } 1085 1086 buf = (float *) cvAlloc( sizeof( float ) * size.width * size.height ); 1087 1088 if( buf == NULL ) 1089 return CV_OUTOFMEM_ERR; 1090 b = buf; 1091 for( i = 0; i < size.height; i++, avg += avgStep, b += size.width ) 1092 for( j = 0; j < size.width; j++ ) 1093 b[j] = avg[j]; 1094 1095 if( ioFlags ) 1096 { 1097 buffer = (float *) cvAlloc( sizeof( float ) * size.width * size.height ); 1098 1099 if( buffer == NULL ) 1100 { 1101 cvFree( &buf ); 1102 return CV_OUTOFMEM_ERR; 1103 } 1104 eigStep = size.width; 1105 } 1106 1107 for( k = 0; k < nEigObjs; k++ ) 1108 { 1109 float *e = ioFlags ? buffer : ((float **) eigInput)[k]; 1110 float c = coeffs[k]; 1111 1112 if( ioFlags ) /* read eigen object */ 1113 { 1114 CvStatus r = (CvStatus)read_callback( k, (void *) buffer, userData ); 1115 1116 if( r ) 1117 { 1118 cvFree( &buf ); 1119 cvFree( &buffer ); 1120 return r; 1121 } 1122 } 1123 1124 b = buf; 1125 for( i = 0; i < size.height; i++, e += eigStep, b += size.width ) 1126 { 1127 for( j = 0; j < size.width - 3; j += 4 ) 1128 { 1129 float b0 = c * e[j]; 1130 float b1 = c * e[j + 1]; 1131 float b2 = c * e[j + 2]; 1132 float b3 = c * e[j + 3]; 1133 1134 b[j] += b0; 1135 b[j + 1] += b1; 1136 b[j + 2] += b2; 1137 b[j + 3] += b3; 1138 } 1139 for( ; j < size.width; j++ ) 1140 b[j] += c * e[j]; 1141 } 1142 } 1143 1144 b = buf; 1145 for( i = 0; i < size.height; i++, avg += avgStep, b += size.width, rest += restStep ) 1146 for( j = 0; j < size.width; j++ ) 1147 { 1148 int w = cvRound( b[j] ); 1149 1150 w = !(w & ~255) ? w : w < 0 ? 0 : 255; 1151 rest[j] = (uchar) w; 1152 } 1153 1154 cvFree( &buf ); 1155 if( ioFlags ) 1156 cvFree( &buffer ); 1157 return CV_NO_ERR; 1158} 1159 1160/*F/////////////////////////////////////////////////////////////////////////////////////// 1161// Name: cvCalcCovarMatrixEx 1162// Purpose: The function calculates a covariance matrix for a group of input objects 1163// (images, vectors, etc.). 1164// Context: 1165// Parameters: nObjects - number of source objects 1166// input - pointer either to array of input objects 1167// or to read callback function (depending on ioFlags) 1168// ioFlags - input/output flags (see Notes to 1169// cvCalcEigenObjects function) 1170// ioBufSize - input/output buffer size 1171// userData - pointer to the structure which contains all necessary 1172// data for the callback functions 1173// avg - averaged object 1174// covarMatrix - covariance matrix (output parameter; must be allocated 1175// before call) 1176// 1177// Notes: See Notes to cvCalcEigenObjects function 1178//F*/ 1179 1180CV_IMPL void 1181cvCalcCovarMatrixEx( int nObjects, void* input, int ioFlags, 1182 int ioBufSize, uchar* buffer, void* userData, 1183 IplImage* avg, float* covarMatrix ) 1184{ 1185 float *avg_data; 1186 int avg_step = 0; 1187 CvSize avg_size; 1188 int i; 1189 1190 CV_FUNCNAME( "cvCalcCovarMatrixEx" ); 1191 1192 __BEGIN__; 1193 1194 cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size ); 1195 if( avg->depth != IPL_DEPTH_32F ) 1196 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1197 if( avg->nChannels != 1 ) 1198 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1199 1200 if( ioFlags == CV_EIGOBJ_NO_CALLBACK ) 1201 { 1202 IplImage **images = (IplImage **) (((CvInput *) & input)->data); 1203 uchar **objects = (uchar **) cvAlloc( sizeof( uchar * ) * nObjects ); 1204 int img_step = 0, old_step = 0; 1205 CvSize img_size = avg_size, old_size = avg_size; 1206 1207 if( objects == NULL ) 1208 CV_ERROR( CV_StsBadArg, "Insufficient memory" ); 1209 1210 for( i = 0; i < nObjects; i++ ) 1211 { 1212 IplImage *img = images[i]; 1213 uchar *img_data; 1214 1215 cvGetImageRawData( img, &img_data, &img_step, &img_size ); 1216 if( img->depth != IPL_DEPTH_8U ) 1217 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1218 if( img_size != avg_size || img_size != old_size ) 1219 CV_ERROR( CV_StsBadArg, "Different sizes of objects" ); 1220 if( img->nChannels != 1 ) 1221 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1222 if( i > 0 && img_step != old_step ) 1223 CV_ERROR( CV_StsBadArg, "Different steps of objects" ); 1224 1225 old_step = img_step; 1226 old_size = img_size; 1227 objects[i] = img_data; 1228 } 1229 1230 CV_CALL( icvCalcCovarMatrixEx_8u32fR( nObjects, 1231 (void*) objects, 1232 img_step, 1233 CV_EIGOBJ_NO_CALLBACK, 1234 0, 1235 NULL, 1236 NULL, 1237 avg_data, 1238 avg_step, 1239 avg_size, 1240 covarMatrix )); 1241 cvFree( &objects ); 1242 } 1243 1244 else 1245 1246 { 1247 CV_CALL( icvCalcCovarMatrixEx_8u32fR( nObjects, 1248 input, 1249 avg_step / 4, 1250 ioFlags, 1251 ioBufSize, 1252 buffer, 1253 userData, 1254 avg_data, 1255 avg_step, 1256 avg_size, 1257 covarMatrix )); 1258 } 1259 1260 __END__; 1261} 1262 1263/*F/////////////////////////////////////////////////////////////////////////////////////// 1264// Name: cvCalcEigenObjects 1265// Purpose: The function calculates an orthonormal eigen basis and a mean (averaged) 1266// object for a group of input objects (images, vectors, etc.). 1267// Context: 1268// Parameters: nObjects - number of source objects 1269// input - pointer either to array of input objects 1270// or to read callback function (depending on ioFlags) 1271// output - pointer either to output eigen objects 1272// or to write callback function (depending on ioFlags) 1273// ioFlags - input/output flags (see Notes) 1274// ioBufSize - input/output buffer size 1275// userData - pointer to the structure which contains all necessary 1276// data for the callback functions 1277// calcLimit - determines the calculation finish conditions 1278// avg - averaged object (has the same size as ROI) 1279// eigVals - pointer to corresponding eigen values (array of <nObjects> 1280// elements in descending order) 1281// 1282// Notes: 1. input/output data (that is, input objects and eigen ones) may either 1283// be allocated in the RAM or be read from/written to the HDD (or any 1284// other device) by read/write callback functions. It depends on the 1285// value of ioFlags paramater, which may be the following: 1286// CV_EIGOBJ_NO_CALLBACK, or 0; 1287// CV_EIGOBJ_INPUT_CALLBACK; 1288// CV_EIGOBJ_OUTPUT_CALLBACK; 1289// CV_EIGOBJ_BOTH_CALLBACK, or 1290// CV_EIGOBJ_INPUT_CALLBACK | CV_EIGOBJ_OUTPUT_CALLBACK. 1291// The callback functions as well as the user data structure must be 1292// developed by the user. 1293// 1294// 2. If ioBufSize = 0, or it's too large, the function dermines buffer size 1295// itself. 1296// 1297// 3. Depending on calcLimit parameter, calculations are finished either if 1298// eigenfaces number comes up to certain value or the relation of the 1299// current eigenvalue and the largest one comes down to certain value 1300// (or any of the above conditions takes place). The calcLimit->type value 1301// must be CV_TERMCRIT_NUMB, CV_TERMCRIT_EPS or 1302// CV_TERMCRIT_NUMB | CV_TERMCRIT_EPS. The function returns the real 1303// values calcLimit->max_iter and calcLimit->epsilon. 1304// 1305// 4. eigVals may be equal to NULL (if you don't need eigen values in further). 1306// 1307//F*/ 1308CV_IMPL void 1309cvCalcEigenObjects( int nObjects, 1310 void* input, 1311 void* output, 1312 int ioFlags, 1313 int ioBufSize, 1314 void* userData, 1315 CvTermCriteria* calcLimit, 1316 IplImage* avg, 1317 float* eigVals ) 1318{ 1319 float *avg_data; 1320 int avg_step = 0; 1321 CvSize avg_size; 1322 int i; 1323 int nEigens = nObjects - 1; 1324 1325 CV_FUNCNAME( "cvCalcEigenObjects" ); 1326 1327 __BEGIN__; 1328 1329 cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size ); 1330 if( avg->depth != IPL_DEPTH_32F ) 1331 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1332 if( avg->nChannels != 1 ) 1333 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1334 1335 if( nEigens > calcLimit->max_iter && calcLimit->type != CV_TERMCRIT_EPS ) 1336 nEigens = calcLimit->max_iter; 1337 1338 switch (ioFlags) 1339 { 1340 case CV_EIGOBJ_NO_CALLBACK: 1341 { 1342 IplImage **objects = (IplImage **) (((CvInput *) & input)->data); 1343 IplImage **eigens = (IplImage **) (((CvInput *) & output)->data); 1344 uchar **objs = (uchar **) cvAlloc( sizeof( uchar * ) * nObjects ); 1345 float **eigs = (float **) cvAlloc( sizeof( float * ) * nEigens ); 1346 int obj_step = 0, old_step = 0; 1347 int eig_step = 0, oldeig_step = 0; 1348 CvSize obj_size = avg_size, old_size = avg_size, 1349 1350 eig_size = avg_size, oldeig_size = avg_size; 1351 1352 if( objects == NULL || eigens == NULL ) 1353 CV_ERROR( CV_StsBadArg, "Insufficient memory" ); 1354 1355 for( i = 0; i < nObjects; i++ ) 1356 { 1357 IplImage *img = objects[i]; 1358 uchar *obj_data; 1359 1360 cvGetImageRawData( img, &obj_data, &obj_step, &obj_size ); 1361 if( img->depth != IPL_DEPTH_8U ) 1362 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1363 if( obj_size != avg_size || obj_size != old_size ) 1364 CV_ERROR( CV_StsBadArg, "Different sizes of objects" ); 1365 if( img->nChannels != 1 ) 1366 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1367 if( i > 0 && obj_step != old_step ) 1368 CV_ERROR( CV_StsBadArg, "Different steps of objects" ); 1369 1370 old_step = obj_step; 1371 old_size = obj_size; 1372 objs[i] = obj_data; 1373 } 1374 for( i = 0; i < nEigens; i++ ) 1375 { 1376 IplImage *eig = eigens[i]; 1377 float *eig_data; 1378 1379 cvGetImageRawData( eig, (uchar **) & eig_data, &eig_step, &eig_size ); 1380 if( eig->depth != IPL_DEPTH_32F ) 1381 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1382 if( eig_size != avg_size || eig_size != oldeig_size ) 1383 CV_ERROR( CV_StsBadArg, "Different sizes of objects" ); 1384 if( eig->nChannels != 1 ) 1385 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1386 if( i > 0 && eig_step != oldeig_step ) 1387 CV_ERROR( CV_StsBadArg, "Different steps of objects" ); 1388 1389 oldeig_step = eig_step; 1390 oldeig_size = eig_size; 1391 eigs[i] = eig_data; 1392 } 1393 CV_CALL( icvCalcEigenObjects_8u32fR( nObjects, (void*) objs, obj_step, 1394 (void*) eigs, eig_step, obj_size, 1395 ioFlags, ioBufSize, userData, 1396 calcLimit, avg_data, avg_step, eigVals )); 1397 cvFree( &objs ); 1398 cvFree( &eigs ); 1399 break; 1400 } 1401 1402 case CV_EIGOBJ_OUTPUT_CALLBACK: 1403 { 1404 IplImage **objects = (IplImage **) (((CvInput *) & input)->data); 1405 uchar **objs = (uchar **) cvAlloc( sizeof( uchar * ) * nObjects ); 1406 int obj_step = 0, old_step = 0; 1407 CvSize obj_size = avg_size, old_size = avg_size; 1408 1409 if( objects == NULL ) 1410 CV_ERROR( CV_StsBadArg, "Insufficient memory" ); 1411 1412 for( i = 0; i < nObjects; i++ ) 1413 { 1414 IplImage *img = objects[i]; 1415 uchar *obj_data; 1416 1417 cvGetImageRawData( img, &obj_data, &obj_step, &obj_size ); 1418 if( img->depth != IPL_DEPTH_8U ) 1419 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1420 if( obj_size != avg_size || obj_size != old_size ) 1421 CV_ERROR( CV_StsBadArg, "Different sizes of objects" ); 1422 if( img->nChannels != 1 ) 1423 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1424 if( i > 0 && obj_step != old_step ) 1425 CV_ERROR( CV_StsBadArg, "Different steps of objects" ); 1426 1427 old_step = obj_step; 1428 old_size = obj_size; 1429 objs[i] = obj_data; 1430 } 1431 CV_CALL( icvCalcEigenObjects_8u32fR( nObjects, 1432 (void*) objs, 1433 obj_step, 1434 output, 1435 avg_step, 1436 obj_size, 1437 ioFlags, 1438 ioBufSize, 1439 userData, 1440 calcLimit, 1441 avg_data, 1442 avg_step, 1443 eigVals )); 1444 cvFree( &objs ); 1445 break; 1446 } 1447 1448 case CV_EIGOBJ_INPUT_CALLBACK: 1449 { 1450 IplImage **eigens = (IplImage **) (((CvInput *) & output)->data); 1451 float **eigs = (float**) cvAlloc( sizeof( float* ) * nEigens ); 1452 int eig_step = 0, oldeig_step = 0; 1453 CvSize eig_size = avg_size, oldeig_size = avg_size; 1454 1455 if( eigens == NULL ) 1456 CV_ERROR( CV_StsBadArg, "Insufficient memory" ); 1457 1458 for( i = 0; i < nEigens; i++ ) 1459 { 1460 IplImage *eig = eigens[i]; 1461 float *eig_data; 1462 1463 cvGetImageRawData( eig, (uchar **) & eig_data, &eig_step, &eig_size ); 1464 if( eig->depth != IPL_DEPTH_32F ) 1465 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1466 if( eig_size != avg_size || eig_size != oldeig_size ) 1467 CV_ERROR( CV_StsBadArg, "Different sizes of objects" ); 1468 if( eig->nChannels != 1 ) 1469 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1470 if( i > 0 && eig_step != oldeig_step ) 1471 CV_ERROR( CV_StsBadArg, "Different steps of objects" ); 1472 1473 oldeig_step = eig_step; 1474 oldeig_size = eig_size; 1475 eigs[i] = eig_data; 1476 } 1477 CV_CALL( icvCalcEigenObjects_8u32fR( nObjects, 1478 input, 1479 avg_step / 4, 1480 (void*) eigs, 1481 eig_step, 1482 eig_size, 1483 ioFlags, 1484 ioBufSize, 1485 userData, 1486 calcLimit, 1487 avg_data, 1488 avg_step, 1489 eigVals )); 1490 cvFree( &eigs ); 1491 break; 1492 } 1493 case CV_EIGOBJ_INPUT_CALLBACK | CV_EIGOBJ_OUTPUT_CALLBACK: 1494 1495 CV_CALL( icvCalcEigenObjects_8u32fR( nObjects, 1496 input, 1497 avg_step / 4, 1498 output, 1499 avg_step, 1500 avg_size, 1501 ioFlags, 1502 ioBufSize, 1503 userData, 1504 calcLimit, 1505 avg_data, 1506 avg_step, 1507 eigVals )); 1508 break; 1509 1510 default: 1511 CV_ERROR( CV_StsBadArg, "Unsupported i/o flag" ); 1512 } 1513 1514 __END__; 1515} 1516 1517/*--------------------------------------------------------------------------------------*/ 1518/*F/////////////////////////////////////////////////////////////////////////////////////// 1519// Name: cvCalcDecompCoeff 1520// Purpose: The function calculates one decomposition coefficient of input object 1521// using previously calculated eigen object and the mean (averaged) object 1522// Context: 1523// Parameters: obj - input object 1524// eigObj - eigen object 1525// avg - averaged object 1526// 1527// Returns: decomposition coefficient value or large negative value (if error) 1528// 1529// Notes: 1530//F*/ 1531 1532CV_IMPL double 1533cvCalcDecompCoeff( IplImage * obj, IplImage * eigObj, IplImage * avg ) 1534{ 1535 double coeff = DBL_MAX; 1536 1537 uchar *obj_data; 1538 float *eig_data; 1539 float *avg_data; 1540 int obj_step = 0, eig_step = 0, avg_step = 0; 1541 CvSize obj_size, eig_size, avg_size; 1542 1543 CV_FUNCNAME( "cvCalcDecompCoeff" ); 1544 1545 __BEGIN__; 1546 1547 cvGetImageRawData( obj, &obj_data, &obj_step, &obj_size ); 1548 if( obj->depth != IPL_DEPTH_8U ) 1549 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1550 if( obj->nChannels != 1 ) 1551 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1552 1553 cvGetImageRawData( eigObj, (uchar **) & eig_data, &eig_step, &eig_size ); 1554 if( eigObj->depth != IPL_DEPTH_32F ) 1555 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1556 if( eigObj->nChannels != 1 ) 1557 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1558 1559 cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size ); 1560 if( avg->depth != IPL_DEPTH_32F ) 1561 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1562 if( avg->nChannels != 1 ) 1563 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1564 1565 if( obj_size != eig_size || obj_size != avg_size ) 1566 CV_ERROR( CV_StsBadArg, "different sizes of images" ); 1567 1568 coeff = icvCalcDecompCoeff_8u32fR( obj_data, obj_step, 1569 eig_data, eig_step, 1570 avg_data, avg_step, obj_size ); 1571 1572 __END__; 1573 1574 return coeff; 1575} 1576 1577/*--------------------------------------------------------------------------------------*/ 1578/*F/////////////////////////////////////////////////////////////////////////////////////// 1579// Names: cvEigenDecomposite 1580// Purpose: The function calculates all decomposition coefficients for input object 1581// using previously calculated eigen objects basis and the mean (averaged) 1582// object 1583// 1584// Parameters: obj - input object 1585// nEigObjs - number of eigen objects 1586// eigInput - pointer either to array of pointers to eigen objects 1587// or to read callback function (depending on ioFlags) 1588// ioFlags - input/output flags 1589// userData - pointer to the structure which contains all necessary 1590// data for the callback function 1591// avg - averaged object 1592// coeffs - calculated coefficients (output data) 1593// 1594// Notes: see notes for cvCalcEigenObjects function 1595//F*/ 1596 1597CV_IMPL void 1598cvEigenDecomposite( IplImage* obj, 1599 int nEigObjs, 1600 void* eigInput, 1601 int ioFlags, 1602 void* userData, 1603 IplImage* avg, 1604 float* coeffs ) 1605{ 1606 float *avg_data; 1607 uchar *obj_data; 1608 int avg_step = 0, obj_step = 0; 1609 CvSize avg_size, obj_size; 1610 int i; 1611 1612 CV_FUNCNAME( "cvEigenDecomposite" ); 1613 1614 __BEGIN__; 1615 1616 cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size ); 1617 if( avg->depth != IPL_DEPTH_32F ) 1618 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1619 if( avg->nChannels != 1 ) 1620 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1621 1622 cvGetImageRawData( obj, &obj_data, &obj_step, &obj_size ); 1623 if( obj->depth != IPL_DEPTH_8U ) 1624 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1625 if( obj->nChannels != 1 ) 1626 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1627 1628 if( obj_size != avg_size ) 1629 CV_ERROR( CV_StsBadArg, "Different sizes of objects" ); 1630 1631 if( ioFlags == CV_EIGOBJ_NO_CALLBACK ) 1632 { 1633 IplImage **eigens = (IplImage **) (((CvInput *) & eigInput)->data); 1634 float **eigs = (float **) cvAlloc( sizeof( float * ) * nEigObjs ); 1635 int eig_step = 0, old_step = 0; 1636 CvSize eig_size = avg_size, old_size = avg_size; 1637 1638 if( eigs == NULL ) 1639 CV_ERROR( CV_StsBadArg, "Insufficient memory" ); 1640 1641 for( i = 0; i < nEigObjs; i++ ) 1642 { 1643 IplImage *eig = eigens[i]; 1644 float *eig_data; 1645 1646 cvGetImageRawData( eig, (uchar **) & eig_data, &eig_step, &eig_size ); 1647 if( eig->depth != IPL_DEPTH_32F ) 1648 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1649 if( eig_size != avg_size || eig_size != old_size ) 1650 CV_ERROR( CV_StsBadArg, "Different sizes of objects" ); 1651 if( eig->nChannels != 1 ) 1652 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1653 if( i > 0 && eig_step != old_step ) 1654 CV_ERROR( CV_StsBadArg, "Different steps of objects" ); 1655 1656 old_step = eig_step; 1657 old_size = eig_size; 1658 eigs[i] = eig_data; 1659 } 1660 1661 CV_CALL( icvEigenDecomposite_8u32fR( obj_data, 1662 obj_step, 1663 nEigObjs, 1664 (void*) eigs, 1665 eig_step, 1666 ioFlags, 1667 userData, 1668 avg_data, 1669 avg_step, 1670 obj_size, 1671 coeffs )); 1672 cvFree( &eigs ); 1673 } 1674 1675 else 1676 1677 { 1678 CV_CALL( icvEigenDecomposite_8u32fR( obj_data, 1679 obj_step, 1680 nEigObjs, 1681 eigInput, 1682 avg_step, 1683 ioFlags, 1684 userData, 1685 avg_data, 1686 avg_step, 1687 obj_size, 1688 coeffs )); 1689 } 1690 1691 __END__; 1692} 1693 1694/*--------------------------------------------------------------------------------------*/ 1695/*F/////////////////////////////////////////////////////////////////////////////////////// 1696// Name: cvEigenProjection 1697// Purpose: The function calculates object projection to the eigen sub-space (restores 1698// an object) using previously calculated eigen objects basis, mean (averaged) 1699// object and decomposition coefficients of the restored object 1700// Context: 1701// Parameters: nEigObjs - number of eigen objects 1702// eigInput - pointer either to array of pointers to eigen objects 1703// or to read callback function (depending on ioFlags) 1704// ioFlags - input/output flags 1705// userData - pointer to the structure which contains all necessary 1706// data for the callback function 1707// coeffs - array of decomposition coefficients 1708// avg - averaged object 1709// proj - object projection (output data) 1710// 1711// Notes: see notes for cvCalcEigenObjects function 1712//F*/ 1713 1714CV_IMPL void 1715cvEigenProjection( void* eigInput, 1716 int nEigObjs, 1717 int ioFlags, 1718 void* userData, 1719 float* coeffs, 1720 IplImage* avg, 1721 IplImage* proj ) 1722{ 1723 float *avg_data; 1724 uchar *proj_data; 1725 int avg_step = 0, proj_step = 0; 1726 CvSize avg_size, proj_size; 1727 int i; 1728 1729 CV_FUNCNAME( "cvEigenProjection" ); 1730 1731 __BEGIN__; 1732 1733 cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size ); 1734 if( avg->depth != IPL_DEPTH_32F ) 1735 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1736 if( avg->nChannels != 1 ) 1737 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1738 1739 cvGetImageRawData( proj, &proj_data, &proj_step, &proj_size ); 1740 if( proj->depth != IPL_DEPTH_8U ) 1741 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1742 if( proj->nChannels != 1 ) 1743 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1744 1745 if( proj_size != avg_size ) 1746 CV_ERROR( CV_StsBadArg, "Different sizes of projects" ); 1747 1748 if( ioFlags == CV_EIGOBJ_NO_CALLBACK ) 1749 { 1750 IplImage **eigens = (IplImage**) (((CvInput *) & eigInput)->data); 1751 float **eigs = (float**) cvAlloc( sizeof( float * ) * nEigObjs ); 1752 int eig_step = 0, old_step = 0; 1753 CvSize eig_size = avg_size, old_size = avg_size; 1754 1755 if( eigs == NULL ) 1756 CV_ERROR( CV_StsBadArg, "Insufficient memory" ); 1757 1758 for( i = 0; i < nEigObjs; i++ ) 1759 { 1760 IplImage *eig = eigens[i]; 1761 float *eig_data; 1762 1763 cvGetImageRawData( eig, (uchar **) & eig_data, &eig_step, &eig_size ); 1764 if( eig->depth != IPL_DEPTH_32F ) 1765 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1766 if( eig_size != avg_size || eig_size != old_size ) 1767 CV_ERROR( CV_StsBadArg, "Different sizes of objects" ); 1768 if( eig->nChannels != 1 ) 1769 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1770 if( i > 0 && eig_step != old_step ) 1771 CV_ERROR( CV_StsBadArg, "Different steps of objects" ); 1772 1773 old_step = eig_step; 1774 old_size = eig_size; 1775 eigs[i] = eig_data; 1776 } 1777 1778 CV_CALL( icvEigenProjection_8u32fR( nEigObjs, 1779 (void*) eigs, 1780 eig_step, 1781 ioFlags, 1782 userData, 1783 coeffs, 1784 avg_data, 1785 avg_step, 1786 proj_data, 1787 proj_step, 1788 avg_size )); 1789 cvFree( &eigs ); 1790 } 1791 1792 else 1793 1794 { 1795 CV_CALL( icvEigenProjection_8u32fR( nEigObjs, 1796 eigInput, 1797 avg_step, 1798 ioFlags, 1799 userData, 1800 coeffs, 1801 avg_data, 1802 avg_step, 1803 proj_data, 1804 proj_step, 1805 avg_size )); 1806 } 1807 1808 __END__; 1809} 1810 1811/* End of file. */ 1812