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 43CvBGCodeBookModel* 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 57void 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 67static uchar satTab8u[768]; 68#undef SAT_8U 69#define SAT_8U(x) satTab8u[(x) + 255] 70 71static 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 86void 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 226int 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 294void 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