Home | History | Annotate | Download | only in src
      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