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
cvCreateBGCodeBookModel()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
cvReleaseBGCodeBookModel(CvBGCodeBookModel ** model)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
icvInitSatTab()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
cvBGCodeBookUpdate(CvBGCodeBookModel * model,const CvArr * _image,CvRect roi,const CvArr * _mask)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
cvBGCodeBookDiff(const CvBGCodeBookModel * model,const CvArr * _image,CvArr * _fgmask,CvRect roi)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
cvBGCodeBookClearStale(CvBGCodeBookModel * model,int staleThresh,CvRect roi,const CvArr * _mask)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