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 //
     12 // Copyright (C) 2000, Intel Corporation, all rights reserved.
     13 // Third party copyrights are property of their respective owners.
     14 //
     15 // Redistribution and use in source and binary forms, with or without modification,
     16 // are permitted provided that the following conditions are met:
     17 //
     18 //   * Redistribution's of source code must retain the above copyright notice,
     19 //     this list of conditions and the following disclaimer.
     20 //
     21 //   * Redistribution's in binary form must reproduce the above copyright notice,
     22 //     this list of conditions and the following disclaimer in the documentation
     23 //     and/or other materials provided with the distribution.
     24 //
     25 //   * The name of Intel Corporation may not be used to endorse or promote products
     26 //     derived from this software without specific prior written permission.
     27 //
     28 // This software is provided by the copyright holders and contributors "as is" and
     29 // any express or implied warranties, including, but not limited to, the implied
     30 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     31 // In no event shall the Intel Corporation or contributors be liable for any direct,
     32 // indirect, incidental, special, exemplary, or consequential damages
     33 // (including, but not limited to, procurement of substitute goods or services;
     34 // loss of use, data, or profits; or business interruption) however caused
     35 // and on any theory of liability, whether in contract, strict liability,
     36 // or tort (including negligence or otherwise) arising in any way out of
     37 // the use of this software, even if advised of the possibility of such damage.
     38 //
     39 //M*/
     40 
     41 #include "_cvaux.h"
     42 
     43 CvBGCodeBookModel* cvCreateBGCodeBookModel()
     44 {
     45     CvBGCodeBookModel* model = (CvBGCodeBookModel*)cvAlloc( sizeof(*model) );
     46     memset( model, 0, sizeof(*model) );
     47     model->cbBounds[0] = model->cbBounds[1] = model->cbBounds[2] = 10;
     48     model->modMin[0] = 3;
     49     model->modMax[0] = 10;
     50     model->modMin[1] = model->modMin[2] = 1;
     51     model->modMax[1] = model->modMax[2] = 1;
     52     model->storage = cvCreateMemStorage();
     53 
     54     return model;
     55 }
     56 
     57 void cvReleaseBGCodeBookModel( CvBGCodeBookModel** model )
     58 {
     59     if( model && *model )
     60     {
     61         cvReleaseMemStorage( &(*model)->storage );
     62         memset( *model, 0, sizeof(**model) );
     63         cvFree( model );
     64     }
     65 }
     66 
     67 static uchar satTab8u[768];
     68 #undef SAT_8U
     69 #define SAT_8U(x) satTab8u[(x) + 255]
     70 
     71 static void icvInitSatTab()
     72 {
     73     static int initialized = 0;
     74     if( !initialized )
     75     {
     76         for( int i = 0; i < 768; i++ )
     77         {
     78             int v = i - 255;
     79             satTab8u[i] = (uchar)(v < 0 ? 0 : v > 255 ? 255 : v);
     80         }
     81         initialized = 1;
     82     }
     83 }
     84 
     85 
     86 void cvBGCodeBookUpdate( CvBGCodeBookModel* model, const CvArr* _image,
     87                          CvRect roi, const CvArr* _mask )
     88 {
     89     CV_FUNCNAME( "cvBGCodeBookUpdate" );
     90 
     91     __BEGIN__;
     92 
     93     CvMat stub, *image = cvGetMat( _image, &stub );
     94     CvMat mstub, *mask = _mask ? cvGetMat( _mask, &mstub ) : 0;
     95     int i, x, y, T;
     96     int nblocks;
     97     uchar cb0, cb1, cb2;
     98     CvBGCodeBookElem* freeList;
     99 
    100     CV_ASSERT( model && CV_MAT_TYPE(image->type) == CV_8UC3 &&
    101         (!mask || CV_IS_MASK_ARR(mask) && CV_ARE_SIZES_EQ(image, mask)) );
    102 
    103     if( roi.x == 0 && roi.y == 0 && roi.width == 0 && roi.height == 0 )
    104     {
    105         roi.width = image->cols;
    106         roi.height = image->rows;
    107     }
    108     else
    109         CV_ASSERT( (unsigned)roi.x < (unsigned)image->cols &&
    110                    (unsigned)roi.y < (unsigned)image->rows &&
    111                    roi.width >= 0 && roi.height >= 0 &&
    112                    roi.x + roi.width <= image->cols &&
    113                    roi.y + roi.height <= image->rows );
    114 
    115     if( image->cols != model->size.width || image->rows != model->size.height )
    116     {
    117         cvClearMemStorage( model->storage );
    118         model->freeList = 0;
    119         cvFree( &model->cbmap );
    120         int bufSz = image->cols*image->rows*sizeof(model->cbmap[0]);
    121         model->cbmap = (CvBGCodeBookElem**)cvAlloc(bufSz);
    122         memset( model->cbmap, 0, bufSz );
    123         model->size = cvSize(image->cols, image->rows);
    124     }
    125 
    126     icvInitSatTab();
    127 
    128     cb0 = model->cbBounds[0];
    129     cb1 = model->cbBounds[1];
    130     cb2 = model->cbBounds[2];
    131 
    132     T = ++model->t;
    133     freeList = model->freeList;
    134     nblocks = (int)((model->storage->block_size - sizeof(CvMemBlock))/sizeof(*freeList));
    135     nblocks = MIN( nblocks, 1024 );
    136     CV_ASSERT( nblocks > 0 );
    137 
    138     for( y = 0; y < roi.height; y++ )
    139     {
    140         const uchar* p = image->data.ptr + image->step*(y + roi.y) + roi.x*3;
    141         const uchar* m = mask ? mask->data.ptr + mask->step*(y + roi.y) + roi.x : 0;
    142         CvBGCodeBookElem** cb = model->cbmap + image->cols*(y + roi.y) + roi.x;
    143 
    144         for( x = 0; x < roi.width; x++, p += 3, cb++ )
    145         {
    146             CvBGCodeBookElem *e, *found = 0;
    147             uchar p0, p1, p2, l0, l1, l2, h0, h1, h2;
    148             int negRun;
    149 
    150             if( m && m[x] == 0 )
    151                 continue;
    152 
    153             p0 = p[0]; p1 = p[1]; p2 = p[2];
    154             l0 = SAT_8U(p0 - cb0); l1 = SAT_8U(p1 - cb1); l2 = SAT_8U(p2 - cb2);
    155             h0 = SAT_8U(p0 + cb0); h1 = SAT_8U(p1 + cb1); h2 = SAT_8U(p2 + cb2);
    156 
    157             for( e = *cb; e != 0; e = e->next )
    158             {
    159                 if( e->learnMin[0] <= p0 && p0 <= e->learnMax[0] &&
    160                     e->learnMin[1] <= p1 && p1 <= e->learnMax[1] &&
    161                     e->learnMin[2] <= p2 && p2 <= e->learnMax[2] )
    162                 {
    163                     e->tLastUpdate = T;
    164                     e->boxMin[0] = MIN(e->boxMin[0], p0);
    165                     e->boxMax[0] = MAX(e->boxMax[0], p0);
    166                     e->boxMin[1] = MIN(e->boxMin[1], p1);
    167                     e->boxMax[1] = MAX(e->boxMax[1], p1);
    168                     e->boxMin[2] = MIN(e->boxMin[2], p2);
    169                     e->boxMax[2] = MAX(e->boxMax[2], p2);
    170 
    171                     // no need to use SAT_8U for updated learnMin[i] & learnMax[i] here,
    172                     // as the bounding li & hi are already within 0..255.
    173                     if( e->learnMin[0] > l0 ) e->learnMin[0]--;
    174                     if( e->learnMax[0] < h0 ) e->learnMax[0]++;
    175                     if( e->learnMin[1] > l1 ) e->learnMin[1]--;
    176                     if( e->learnMax[1] < h1 ) e->learnMax[1]++;
    177                     if( e->learnMin[2] > l2 ) e->learnMin[2]--;
    178                     if( e->learnMax[2] < h2 ) e->learnMax[2]++;
    179 
    180                     found = e;
    181                     break;
    182                 }
    183                 negRun = T - e->tLastUpdate;
    184                 e->stale = MAX( e->stale, negRun );
    185             }
    186 
    187             for( ; e != 0; e = e->next )
    188             {
    189                 negRun = T - e->tLastUpdate;
    190                 e->stale = MAX( e->stale, negRun );
    191             }
    192 
    193             if( !found )
    194             {
    195                 if( !freeList )
    196                 {
    197                     freeList = (CvBGCodeBookElem*)cvMemStorageAlloc(model->storage,
    198                         nblocks*sizeof(*freeList));
    199                     for( i = 0; i < nblocks-1; i++ )
    200                         freeList[i].next = &freeList[i+1];
    201                     freeList[nblocks-1].next = 0;
    202                 }
    203                 e = freeList;
    204                 freeList = freeList->next;
    205 
    206                 e->learnMin[0] = l0; e->learnMax[0] = h0;
    207                 e->learnMin[1] = l1; e->learnMax[1] = h1;
    208                 e->learnMin[2] = l2; e->learnMax[2] = h2;
    209                 e->boxMin[0] = e->boxMax[0] = p0;
    210                 e->boxMin[1] = e->boxMax[1] = p1;
    211                 e->boxMin[2] = e->boxMax[2] = p2;
    212                 e->tLastUpdate = T;
    213                 e->stale = 0;
    214                 e->next = *cb;
    215                 *cb = e;
    216             }
    217         }
    218     }
    219 
    220     model->freeList = freeList;
    221 
    222     __END__;
    223 }
    224 
    225 
    226 int cvBGCodeBookDiff( const CvBGCodeBookModel* model, const CvArr* _image,
    227                       CvArr* _fgmask, CvRect roi )
    228 {
    229     int maskCount = -1;
    230 
    231     CV_FUNCNAME( "cvBGCodeBookDiff" );
    232 
    233     __BEGIN__;
    234 
    235     CvMat stub, *image = cvGetMat( _image, &stub );
    236     CvMat mstub, *mask = cvGetMat( _fgmask, &mstub );
    237     int x, y;
    238     uchar m0, m1, m2, M0, M1, M2;
    239 
    240     CV_ASSERT( model && CV_MAT_TYPE(image->type) == CV_8UC3 &&
    241         image->cols == model->size.width && image->rows == model->size.height &&
    242         CV_IS_MASK_ARR(mask) && CV_ARE_SIZES_EQ(image, mask) );
    243 
    244     if( roi.x == 0 && roi.y == 0 && roi.width == 0 && roi.height == 0 )
    245     {
    246         roi.width = image->cols;
    247         roi.height = image->rows;
    248     }
    249     else
    250         CV_ASSERT( (unsigned)roi.x < (unsigned)image->cols &&
    251                    (unsigned)roi.y < (unsigned)image->rows &&
    252                    roi.width >= 0 && roi.height >= 0 &&
    253                    roi.x + roi.width <= image->cols &&
    254                    roi.y + roi.height <= image->rows );
    255 
    256     m0 = model->modMin[0]; M0 = model->modMax[0];
    257     m1 = model->modMin[1]; M1 = model->modMax[1];
    258     m2 = model->modMin[2]; M2 = model->modMax[2];
    259 
    260     maskCount = roi.height*roi.width;
    261     for( y = 0; y < roi.height; y++ )
    262     {
    263         const uchar* p = image->data.ptr + image->step*(y + roi.y) + roi.x*3;
    264         uchar* m = mask->data.ptr + mask->step*(y + roi.y) + roi.x;
    265         CvBGCodeBookElem** cb = model->cbmap + image->cols*(y + roi.y) + roi.x;
    266 
    267         for( x = 0; x < roi.width; x++, p += 3, cb++ )
    268         {
    269             CvBGCodeBookElem *e;
    270             uchar p0 = p[0], p1 = p[1], p2 = p[2];
    271             int l0 = p0 + m0, l1 = p1 + m1, l2 = p2 + m2;
    272             int h0 = p0 - M0, h1 = p1 - M1, h2 = p2 - M2;
    273             m[x] = (uchar)255;
    274 
    275             for( e = *cb; e != 0; e = e->next )
    276             {
    277                 if( e->boxMin[0] <= l0 && h0 <= e->boxMax[0] &&
    278                     e->boxMin[1] <= l1 && h1 <= e->boxMax[1] &&
    279                     e->boxMin[2] <= l2 && h2 <= e->boxMax[2] )
    280                 {
    281                     m[x] = 0;
    282                     maskCount--;
    283                     break;
    284                 }
    285             }
    286         }
    287     }
    288 
    289     __END__;
    290 
    291     return maskCount;
    292 }
    293 
    294 void cvBGCodeBookClearStale( CvBGCodeBookModel* model, int staleThresh,
    295                              CvRect roi, const CvArr* _mask )
    296 {
    297     CV_FUNCNAME( "cvBGCodeBookClearStale" );
    298 
    299     __BEGIN__;
    300 
    301     CvMat mstub, *mask = _mask ? cvGetMat( _mask, &mstub ) : 0;
    302     int x, y, T;
    303     CvBGCodeBookElem* freeList;
    304 
    305     CV_ASSERT( model && (!mask || CV_IS_MASK_ARR(mask) &&
    306         mask->cols == model->size.width && mask->rows == model->size.height) );
    307 
    308     if( roi.x == 0 && roi.y == 0 && roi.width == 0 && roi.height == 0 )
    309     {
    310         roi.width = model->size.width;
    311         roi.height = model->size.height;
    312     }
    313     else
    314         CV_ASSERT( (unsigned)roi.x < (unsigned)mask->cols &&
    315                    (unsigned)roi.y < (unsigned)mask->rows &&
    316                    roi.width >= 0 && roi.height >= 0 &&
    317                    roi.x + roi.width <= mask->cols &&
    318                    roi.y + roi.height <= mask->rows );
    319 
    320     icvInitSatTab();
    321     freeList = model->freeList;
    322     T = model->t;
    323 
    324     for( y = 0; y < roi.height; y++ )
    325     {
    326         const uchar* m = mask ? mask->data.ptr + mask->step*(y + roi.y) + roi.x : 0;
    327         CvBGCodeBookElem** cb = model->cbmap + model->size.width*(y + roi.y) + roi.x;
    328 
    329         for( x = 0; x < roi.width; x++, cb++ )
    330         {
    331             CvBGCodeBookElem *e, first, *prev = &first;
    332 
    333             if( m && m[x] == 0 )
    334                 continue;
    335 
    336             for( first.next = e = *cb; e != 0; e = prev->next )
    337             {
    338                 if( e->stale > staleThresh )
    339                 {
    340                     prev->next = e->next;
    341                     e->next = freeList;
    342                     freeList = e;
    343                 }
    344                 else
    345                 {
    346                     e->stale = 0;
    347                     e->tLastUpdate = T;
    348                     prev = e;
    349                 }
    350             }
    351 
    352             *cb = first.next;
    353         }
    354     }
    355 
    356     model->freeList = freeList;
    357 
    358     __END__;
    359 }
    360 
    361 /* End of file. */
    362 
    363