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 #include "_cvaux.h" 42 43 //*F/////////////////////////////////////////////////////////////////////////////////////// 44 // Name: icvImgToObs_DCT_8u32f_C1R 45 // Purpose: The function takes as input an image and returns the sequnce of observations 46 // to be used with an embedded HMM; Each observation is top-left block of DCT 47 // coefficient matrix. 48 // Context: 49 // Parameters: img - pointer to the original image ROI 50 // imgStep - full row width of the image in bytes 51 // roi - width and height of ROI in pixels 52 // obs - pointer to resultant observation vectors 53 // dctSize - size of the block for which DCT is calculated 54 // obsSize - size of top-left block of DCT coeffs matrix, which is treated 55 // as observation. Each observation vector consists of 56 // obsSize.width * obsSize.height floats. 57 // The following conditions should be satisfied: 58 // 0 < objSize.width <= dctSize.width, 59 // 0 < objSize.height <= dctSize.height. 60 // delta - dctBlocks are overlapped and this parameter specifies horizontal 61 // and vertical shift. 62 // Returns: 63 // CV_NO_ERR or error code 64 // Notes: 65 // The algorithm is following: 66 // 1. First, number of observation vectors per row and per column are calculated: 67 // 68 // Nx = floor((roi.width - dctSize.width + delta.width)/delta.width); 69 // Ny = floor((roi.height - dctSize.height + delta.height)/delta.height); 70 // 71 // So, total number of observation vectors is Nx*Ny, and total size of 72 // array obs must be >= Nx*Ny*obsSize.width*obsSize.height*sizeof(float). 73 // 2. Observation vectors are calculated in the following loop 74 // ( actual implementation may be different ), where 75 // I[x1:x2,y1:y2] means block of pixels from source image with 76 // x1 <= x < x2, y1 <= y < y2, 77 // D[x1:x2,y1:y2] means sub matrix of DCT matrix D. 78 // O[x,y] means observation vector that corresponds to position 79 // (x*delta.width,y*delta.height) in the source image 80 // ( all indices are counted from 0 ). 81 // 82 // for( y = 0; y < Ny; y++ ) 83 // { 84 // for( x = 0; x < Nx; x++ ) 85 // { 86 // D = DCT(I[x*delta.width : x*delta.width + dctSize.width, 87 // y*delta.height : y*delta.height + dctSize.height]); 88 // O[x,y] = D[0:obsSize.width, 0:obsSize.height]; 89 // } 90 // } 91 //F*/ 92 93 /*comment out the following line to make DCT be calculated in floating-point arithmetics*/ 94 //#define _CV_INT_DCT 95 96 /* for integer DCT only */ 97 #define DCT_SCALE 15 98 99 #ifdef _CV_INT_DCT 100 typedef int work_t; 101 102 #define DESCALE CV_DESCALE 103 #define SCALE(x) CV_FLT_TO_FIX((x),DCT_SCALE) 104 #else 105 typedef float work_t; 106 107 #define DESCALE(x,n) (float)(x) 108 #define SCALE(x) (float)(x) 109 #endif 110 111 /* calculate dct transform matrix */ 112 static void icvCalcDCTMatrix( work_t * cfs, int n ); 113 114 #define MAX_DCT_SIZE 32 115 116 static CvStatus CV_STDCALL 117 icvImgToObs_DCT_8u32f_C1R( uchar * img, int imgStep, CvSize roi, 118 float *obs, CvSize dctSize, 119 CvSize obsSize, CvSize delta ) 120 { 121 /* dct transform matrices: horizontal and vertical */ 122 work_t tab_x[MAX_DCT_SIZE * MAX_DCT_SIZE / 2 + 2]; 123 work_t tab_y[MAX_DCT_SIZE * MAX_DCT_SIZE / 2 + 2]; 124 125 /* temporary buffers for dct */ 126 work_t temp0[MAX_DCT_SIZE * 4]; 127 work_t temp1[MAX_DCT_SIZE * 4]; 128 work_t *buffer = 0; 129 work_t *buf_limit; 130 131 double s; 132 133 int y; 134 int Nx, Ny; 135 136 int n1 = dctSize.height, m1 = n1 / 2; 137 int n2 = dctSize.width, m2 = n2 / 2; 138 139 if( !img || !obs ) 140 return CV_NULLPTR_ERR; 141 142 if( roi.width <= 0 || roi.height <= 0 ) 143 return CV_BADSIZE_ERR; 144 145 if( delta.width <= 0 || delta.height <= 0 ) 146 return CV_BADRANGE_ERR; 147 148 if( obsSize.width <= 0 || dctSize.width < obsSize.width || 149 obsSize.height <= 0 || dctSize.height < obsSize.height ) 150 return CV_BADRANGE_ERR; 151 152 if( dctSize.width > MAX_DCT_SIZE || dctSize.height > MAX_DCT_SIZE ) 153 return CV_BADRANGE_ERR; 154 155 Nx = (roi.width - dctSize.width + delta.width) / delta.width; 156 Ny = (roi.height - dctSize.height + delta.height) / delta.height; 157 158 if( Nx <= 0 || Ny <= 0 ) 159 return CV_BADRANGE_ERR; 160 161 buffer = (work_t *)cvAlloc( roi.width * obsSize.height * sizeof( buffer[0] )); 162 if( !buffer ) 163 return CV_OUTOFMEM_ERR; 164 165 icvCalcDCTMatrix( tab_x, dctSize.width ); 166 icvCalcDCTMatrix( tab_y, dctSize.height ); 167 168 buf_limit = buffer + obsSize.height * roi.width; 169 170 for( y = 0; y < Ny; y++, img += delta.height * imgStep ) 171 { 172 int x, i, j, k; 173 work_t k0 = 0; 174 175 /* do transfroms for each column. Calc only first obsSize.height DCT coefficients */ 176 for( x = 0; x < roi.width; x++ ) 177 { 178 float is = 0; 179 work_t *buf = buffer + x; 180 work_t *tab = tab_y + 2; 181 182 if( n1 & 1 ) 183 { 184 is = img[x + m1 * imgStep]; 185 k0 = ((work_t) is) * tab[-1]; 186 } 187 188 /* first coefficient */ 189 for( j = 0; j < m1; j++ ) 190 { 191 float t0 = img[x + j * imgStep]; 192 float t1 = img[x + (n1 - 1 - j) * imgStep]; 193 float t2 = t0 + t1; 194 195 t0 -= t1; 196 temp0[j] = (work_t) t2; 197 is += t2; 198 temp1[j] = (work_t) t0; 199 } 200 201 buf[0] = DESCALE( is * tab[-2], PASS1_SHIFT ); 202 if( (buf += roi.width) >= buf_limit ) 203 continue; 204 205 /* other coefficients */ 206 for( ;; ) 207 { 208 s = 0; 209 210 for( k = 0; k < m1; k++ ) 211 s += temp1[k] * tab[k]; 212 213 buf[0] = DESCALE( s, PASS1_SHIFT ); 214 if( (buf += roi.width) >= buf_limit ) 215 break; 216 217 tab += m1; 218 s = 0; 219 220 if( n1 & 1 ) 221 { 222 k0 = -k0; 223 s = k0; 224 } 225 for( k = 0; k < m1; k++ ) 226 s += temp0[k] * tab[k]; 227 228 buf[0] = DESCALE( s, PASS1_SHIFT ); 229 tab += m1; 230 231 if( (buf += roi.width) >= buf_limit ) 232 break; 233 } 234 } 235 236 k0 = 0; 237 238 /* do transforms for rows. */ 239 for( x = 0; x + dctSize.width <= roi.width; x += delta.width ) 240 { 241 for( i = 0; i < obsSize.height; i++ ) 242 { 243 work_t *buf = buffer + x + roi.width * i; 244 work_t *tab = tab_x + 2; 245 float *obs_limit = obs + obsSize.width; 246 247 s = 0; 248 249 if( n2 & 1 ) 250 { 251 s = buf[m2]; 252 k0 = (work_t) (s * tab[-1]); 253 } 254 255 /* first coefficient */ 256 for( j = 0; j < m2; j++ ) 257 { 258 work_t t0 = buf[j]; 259 work_t t1 = buf[n2 - 1 - j]; 260 work_t t2 = t0 + t1; 261 262 t0 -= t1; 263 temp0[j] = (work_t) t2; 264 s += t2; 265 temp1[j] = (work_t) t0; 266 } 267 268 *obs++ = (float) DESCALE( s * tab[-2], PASS2_SHIFT ); 269 270 if( obs == obs_limit ) 271 continue; 272 273 /* other coefficients */ 274 for( ;; ) 275 { 276 s = 0; 277 278 for( k = 0; k < m2; k++ ) 279 s += temp1[k] * tab[k]; 280 281 obs[0] = (float) DESCALE( s, PASS2_SHIFT ); 282 if( ++obs == obs_limit ) 283 break; 284 285 tab += m2; 286 287 s = 0; 288 289 if( n2 & 1 ) 290 { 291 k0 = -k0; 292 s = k0; 293 } 294 for( k = 0; k < m2; k++ ) 295 s += temp0[k] * tab[k]; 296 obs[0] = (float) DESCALE( s, PASS2_SHIFT ); 297 298 tab += m2; 299 if( ++obs == obs_limit ) 300 break; 301 } 302 } 303 } 304 } 305 306 cvFree( &buffer ); 307 return CV_NO_ERR; 308 } 309 310 311 static CvStatus CV_STDCALL 312 icvImgToObs_DCT_32f_C1R( float * img, int imgStep, CvSize roi, 313 float *obs, CvSize dctSize, 314 CvSize obsSize, CvSize delta ) 315 { 316 /* dct transform matrices: horizontal and vertical */ 317 work_t tab_x[MAX_DCT_SIZE * MAX_DCT_SIZE / 2 + 2]; 318 work_t tab_y[MAX_DCT_SIZE * MAX_DCT_SIZE / 2 + 2]; 319 320 /* temporary buffers for dct */ 321 work_t temp0[MAX_DCT_SIZE * 4]; 322 work_t temp1[MAX_DCT_SIZE * 4]; 323 work_t *buffer = 0; 324 work_t *buf_limit; 325 326 double s; 327 328 int y; 329 int Nx, Ny; 330 331 int n1 = dctSize.height, m1 = n1 / 2; 332 int n2 = dctSize.width, m2 = n2 / 2; 333 334 if( !img || !obs ) 335 return CV_NULLPTR_ERR; 336 337 if( roi.width <= 0 || roi.height <= 0 ) 338 return CV_BADSIZE_ERR; 339 340 if( delta.width <= 0 || delta.height <= 0 ) 341 return CV_BADRANGE_ERR; 342 343 if( obsSize.width <= 0 || dctSize.width < obsSize.width || 344 obsSize.height <= 0 || dctSize.height < obsSize.height ) 345 return CV_BADRANGE_ERR; 346 347 if( dctSize.width > MAX_DCT_SIZE || dctSize.height > MAX_DCT_SIZE ) 348 return CV_BADRANGE_ERR; 349 350 Nx = (roi.width - dctSize.width + delta.width) / delta.width; 351 Ny = (roi.height - dctSize.height + delta.height) / delta.height; 352 353 if( Nx <= 0 || Ny <= 0 ) 354 return CV_BADRANGE_ERR; 355 356 buffer = (work_t *)cvAlloc( roi.width * obsSize.height * sizeof( buffer[0] )); 357 if( !buffer ) 358 return CV_OUTOFMEM_ERR; 359 360 icvCalcDCTMatrix( tab_x, dctSize.width ); 361 icvCalcDCTMatrix( tab_y, dctSize.height ); 362 363 buf_limit = buffer + obsSize.height * roi.width; 364 365 imgStep /= sizeof(img[0]); 366 367 for( y = 0; y < Ny; y++, img += delta.height * imgStep ) 368 { 369 int x, i, j, k; 370 work_t k0 = 0; 371 372 /* do transfroms for each column. Calc only first obsSize.height DCT coefficients */ 373 for( x = 0; x < roi.width; x++ ) 374 { 375 float is = 0; 376 work_t *buf = buffer + x; 377 work_t *tab = tab_y + 2; 378 379 if( n1 & 1 ) 380 { 381 is = img[x + m1 * imgStep]; 382 k0 = ((work_t) is) * tab[-1]; 383 } 384 385 /* first coefficient */ 386 for( j = 0; j < m1; j++ ) 387 { 388 float t0 = img[x + j * imgStep]; 389 float t1 = img[x + (n1 - 1 - j) * imgStep]; 390 float t2 = t0 + t1; 391 392 t0 -= t1; 393 temp0[j] = (work_t) t2; 394 is += t2; 395 temp1[j] = (work_t) t0; 396 } 397 398 buf[0] = DESCALE( is * tab[-2], PASS1_SHIFT ); 399 if( (buf += roi.width) >= buf_limit ) 400 continue; 401 402 /* other coefficients */ 403 for( ;; ) 404 { 405 s = 0; 406 407 for( k = 0; k < m1; k++ ) 408 s += temp1[k] * tab[k]; 409 410 buf[0] = DESCALE( s, PASS1_SHIFT ); 411 if( (buf += roi.width) >= buf_limit ) 412 break; 413 414 tab += m1; 415 s = 0; 416 417 if( n1 & 1 ) 418 { 419 k0 = -k0; 420 s = k0; 421 } 422 for( k = 0; k < m1; k++ ) 423 s += temp0[k] * tab[k]; 424 425 buf[0] = DESCALE( s, PASS1_SHIFT ); 426 tab += m1; 427 428 if( (buf += roi.width) >= buf_limit ) 429 break; 430 } 431 } 432 433 k0 = 0; 434 435 /* do transforms for rows. */ 436 for( x = 0; x + dctSize.width <= roi.width; x += delta.width ) 437 { 438 for( i = 0; i < obsSize.height; i++ ) 439 { 440 work_t *buf = buffer + x + roi.width * i; 441 work_t *tab = tab_x + 2; 442 float *obs_limit = obs + obsSize.width; 443 444 s = 0; 445 446 if( n2 & 1 ) 447 { 448 s = buf[m2]; 449 k0 = (work_t) (s * tab[-1]); 450 } 451 452 /* first coefficient */ 453 for( j = 0; j < m2; j++ ) 454 { 455 work_t t0 = buf[j]; 456 work_t t1 = buf[n2 - 1 - j]; 457 work_t t2 = t0 + t1; 458 459 t0 -= t1; 460 temp0[j] = (work_t) t2; 461 s += t2; 462 temp1[j] = (work_t) t0; 463 } 464 465 *obs++ = (float) DESCALE( s * tab[-2], PASS2_SHIFT ); 466 467 if( obs == obs_limit ) 468 continue; 469 470 /* other coefficients */ 471 for( ;; ) 472 { 473 s = 0; 474 475 for( k = 0; k < m2; k++ ) 476 s += temp1[k] * tab[k]; 477 478 obs[0] = (float) DESCALE( s, PASS2_SHIFT ); 479 if( ++obs == obs_limit ) 480 break; 481 482 tab += m2; 483 484 s = 0; 485 486 if( n2 & 1 ) 487 { 488 k0 = -k0; 489 s = k0; 490 } 491 for( k = 0; k < m2; k++ ) 492 s += temp0[k] * tab[k]; 493 obs[0] = (float) DESCALE( s, PASS2_SHIFT ); 494 495 tab += m2; 496 if( ++obs == obs_limit ) 497 break; 498 } 499 } 500 } 501 } 502 503 cvFree( &buffer ); 504 return CV_NO_ERR; 505 } 506 507 508 static void 509 icvCalcDCTMatrix( work_t * cfs, int n ) 510 { 511 static const double sqrt2 = 1.4142135623730950488016887242097; 512 static const double pi = 3.1415926535897932384626433832795; 513 514 static const double sincos[16 * 2] = { 515 1.00000000000000000, 0.00000000000000006, 516 0.70710678118654746, 0.70710678118654757, 517 0.49999999999999994, 0.86602540378443871, 518 0.38268343236508978, 0.92387953251128674, 519 0.30901699437494740, 0.95105651629515353, 520 0.25881904510252074, 0.96592582628906831, 521 0.22252093395631439, 0.97492791218182362, 522 0.19509032201612825, 0.98078528040323043, 523 0.17364817766693033, 0.98480775301220802, 524 0.15643446504023087, 0.98768834059513777, 525 0.14231483827328514, 0.98982144188093268, 526 0.13052619222005157, 0.99144486137381038, 527 0.12053668025532305, 0.99270887409805397, 528 0.11196447610330786, 0.99371220989324260, 529 0.10452846326765346, 0.99452189536827329, 530 0.09801714032956060, 0.99518472667219693, 531 }; 532 533 #define ROTATE( c, s, dc, ds ) \ 534 { \ 535 t = c*dc - s*ds; \ 536 s = c*ds + s*dc; \ 537 c = t; \ 538 } 539 540 #define WRITE2( j, a, b ) \ 541 { \ 542 cfs[j] = SCALE(a); \ 543 cfs2[j] = SCALE(b); \ 544 } 545 546 double t, scale = 1. / sqrt( (double)n ); 547 int i, j, m = n / 2; 548 549 cfs[0] = SCALE( scale ); 550 scale *= sqrt2; 551 cfs[1] = SCALE( scale ); 552 cfs += 2 - m; 553 554 if( n > 1 ) 555 { 556 double a0, b0; 557 double da0, db0; 558 work_t *cfs2 = cfs + m * n; 559 560 if( n <= 16 ) 561 { 562 da0 = a0 = sincos[2 * n - 1]; 563 db0 = b0 = sincos[2 * n - 2]; 564 } 565 else 566 { 567 t = pi / (2 * n); 568 da0 = a0 = cos( t ); 569 db0 = b0 = sin( t ); 570 } 571 572 /* other rows */ 573 for( i = 1; i <= m; i++ ) 574 { 575 double a = a0 * scale; 576 double b = b0 * scale; 577 double da = a0 * a0 - b0 * b0; 578 double db = a0 * b0 + a0 * b0; 579 580 cfs += m; 581 cfs2 -= m; 582 583 for( j = 0; j < m; j += 2 ) 584 { 585 WRITE2( j, a, b ); 586 ROTATE( a, b, da, db ); 587 if( j + 1 < m ) 588 { 589 WRITE2( j + 1, a, -b ); 590 ROTATE( a, b, da, db ); 591 } 592 } 593 594 ROTATE( a0, b0, da0, db0 ); 595 } 596 } 597 #undef ROTATE 598 #undef WRITE2 599 } 600 601 602 CV_IMPL void 603 cvImgToObs_DCT( const void* arr, float *obs, CvSize dctSize, 604 CvSize obsSize, CvSize delta ) 605 { 606 CV_FUNCNAME( "cvImgToObs_DCT" ); 607 608 __BEGIN__; 609 610 CvMat stub, *mat = (CvMat*)arr; 611 612 CV_CALL( mat = cvGetMat( arr, &stub )); 613 614 switch( CV_MAT_TYPE( mat->type )) 615 { 616 case CV_8UC1: 617 IPPI_CALL( icvImgToObs_DCT_8u32f_C1R( mat->data.ptr, mat->step, 618 cvGetMatSize(mat), obs, 619 dctSize, obsSize, delta )); 620 break; 621 case CV_32FC1: 622 IPPI_CALL( icvImgToObs_DCT_32f_C1R( mat->data.fl, mat->step, 623 cvGetMatSize(mat), obs, 624 dctSize, obsSize, delta )); 625 break; 626 default: 627 CV_ERROR( CV_StsUnsupportedFormat, "" ); 628 } 629 630 __END__; 631 } 632 633 634 /* End of file. */ 635