1 /*M///////////////////////////////////////////////////////////////////////////////////////
\r
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
\r
5 // By downloading, copying, installing or using the software you agree to this license.
\r
6 // If you do not agree to this license, do not download, install,
\r
7 // copy or use the software.
\r
10 // Intel License Agreement
\r
11 // For Open Source Computer Vision Library
\r
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
\r
14 // Third party copyrights are property of their respective owners.
\r
16 // Redistribution and use in source and binary forms, with or without modification,
\r
17 // are permitted provided that the following conditions are met:
\r
19 // * Redistribution's of source code must retain the above copyright notice,
\r
20 // this list of conditions and the following disclaimer.
\r
22 // * Redistribution's in binary form must reproduce the above copyright notice,
\r
23 // this list of conditions and the following disclaimer in the documentation
\r
24 // and/or other materials provided with the distribution.
\r
26 // * The name of Intel Corporation may not be used to endorse or promote products
\r
27 // derived from this software without specific prior written permission.
\r
29 // This software is provided by the copyright holders and contributors "as is" and
\r
30 // any express or implied warranties, including, but not limited to, the implied
\r
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
\r
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
\r
33 // indirect, incidental, special, exemplary, or consequential damages
\r
34 // (including, but not limited to, procurement of substitute goods or services;
\r
35 // loss of use, data, or profits; or business interruption) however caused
\r
36 // and on any theory of liability, whether in contract, strict liability,
\r
37 // or tort (including negligence or otherwise) arising in any way out of
\r
38 // the use of this software, even if advised of the possibility of such damage.
\r
44 typedef struct CvFFillSegment
\r
58 #define ICV_PUSH( Y, L, R, PREV_L, PREV_R, DIR )\
\r
60 tail->y = (ushort)(Y); \
\r
61 tail->l = (ushort)(L); \
\r
62 tail->r = (ushort)(R); \
\r
63 tail->prevl = (ushort)(PREV_L); \
\r
64 tail->prevr = (ushort)(PREV_R); \
\r
65 tail->dir = (short)(DIR); \
\r
66 if( ++tail >= buffer_end ) \
\r
71 #define ICV_POP( Y, L, R, PREV_L, PREV_R, DIR ) \
\r
76 PREV_L = head->prevl; \
\r
77 PREV_R = head->prevr; \
\r
79 if( ++head >= buffer_end ) \
\r
84 #define ICV_EQ_C3( p1, p2 ) \
\r
85 ((p1)[0] == (p2)[0] && (p1)[1] == (p2)[1] && (p1)[2] == (p2)[2])
\r
87 #define ICV_SET_C3( p, q ) \
\r
88 ((p)[0] = (q)[0], (p)[1] = (q)[1], (p)[2] = (q)[2])
\r
90 /****************************************************************************************\
\r
91 * Simple Floodfill (repainting single-color connected component) *
\r
92 \****************************************************************************************/
\r
95 icvFloodFill_8u_CnIR( uchar* pImage, int step, CvSize roi, CvPoint seed,
\r
96 uchar* _newVal, CvConnectedComp* region, int flags,
\r
97 CvFFillSegment* buffer, int buffer_size, int cn )
\r
99 uchar* img = pImage + step * seed.y;
\r
102 int val0[] = {0,0,0};
\r
103 uchar newVal[] = {0,0,0};
\r
104 int XMin, XMax, YMin = seed.y, YMax = seed.y;
\r
105 int _8_connectivity = (flags & 255) == 8;
\r
106 CvFFillSegment* buffer_end = buffer + buffer_size, *head = buffer, *tail = buffer;
\r
108 L = R = XMin = XMax = seed.x;
\r
113 newVal[0] = _newVal[0];
\r
115 img[L] = newVal[0];
\r
117 while( ++R < roi.width && img[R] == val0[0] )
\r
118 img[R] = newVal[0];
\r
120 while( --L >= 0 && img[L] == val0[0] )
\r
121 img[L] = newVal[0];
\r
126 ICV_SET_C3( val0, img + L*3 );
\r
127 ICV_SET_C3( newVal, _newVal );
\r
129 ICV_SET_C3( img + L*3, newVal );
\r
131 while( --L >= 0 && ICV_EQ_C3( img + L*3, val0 ))
\r
132 ICV_SET_C3( img + L*3, newVal );
\r
134 while( ++R < roi.width && ICV_EQ_C3( img + R*3, val0 ))
\r
135 ICV_SET_C3( img + R*3, newVal );
\r
140 ICV_PUSH( seed.y, L, R, R + 1, R, UP );
\r
142 while( head != tail )
\r
144 int k, YC, PL, PR, dir;
\r
145 ICV_POP( YC, L, R, PL, PR, dir );
\r
149 {-dir, L - _8_connectivity, R + _8_connectivity},
\r
150 {dir, L - _8_connectivity, PL - 1},
\r
151 {dir, PR + 1, R + _8_connectivity}
\r
158 if( XMax < R ) XMax = R;
\r
159 if( XMin > L ) XMin = L;
\r
160 if( YMax < YC ) YMax = YC;
\r
161 if( YMin > YC ) YMin = YC;
\r
164 for( k = 0/*(unsigned)(YC - dir) >= (unsigned)roi.height*/; k < 3; k++ )
\r
167 img = pImage + (YC + dir) * step;
\r
168 int left = data[k][1];
\r
169 int right = data[k][2];
\r
171 if( (unsigned)(YC + dir) >= (unsigned)roi.height )
\r
175 for( i = left; i <= right; i++ )
\r
177 if( (unsigned)i < (unsigned)roi.width && img[i] == val0[0] )
\r
180 img[i] = newVal[0];
\r
181 while( --j >= 0 && img[j] == val0[0] )
\r
182 img[j] = newVal[0];
\r
184 while( ++i < roi.width && img[i] == val0[0] )
\r
185 img[i] = newVal[0];
\r
187 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
\r
191 for( i = left; i <= right; i++ )
\r
193 if( (unsigned)i < (unsigned)roi.width && ICV_EQ_C3( img + i*3, val0 ))
\r
196 ICV_SET_C3( img + i*3, newVal );
\r
197 while( --j >= 0 && ICV_EQ_C3( img + j*3, val0 ))
\r
198 ICV_SET_C3( img + j*3, newVal );
\r
200 while( ++i < roi.width && ICV_EQ_C3( img + i*3, val0 ))
\r
201 ICV_SET_C3( img + i*3, newVal );
\r
203 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
\r
211 region->area = area;
\r
212 region->rect.x = XMin;
\r
213 region->rect.y = YMin;
\r
214 region->rect.width = XMax - XMin + 1;
\r
215 region->rect.height = YMax - YMin + 1;
\r
216 region->value = cvScalar(newVal[0], newVal[1], newVal[2], 0);
\r
223 /* because all the operations on floats that are done during non-gradient floodfill
\r
224 are just copying and comparison on equality,
\r
225 we can do the whole op on 32-bit integers instead */
\r
227 icvFloodFill_32f_CnIR( int* pImage, int step, CvSize roi, CvPoint seed,
\r
228 int* _newVal, CvConnectedComp* region, int flags,
\r
229 CvFFillSegment* buffer, int buffer_size, int cn )
\r
231 int* img = pImage + (step /= sizeof(pImage[0])) * seed.y;
\r
234 int val0[] = {0,0,0};
\r
235 int newVal[] = {0,0,0};
\r
236 int XMin, XMax, YMin = seed.y, YMax = seed.y;
\r
237 int _8_connectivity = (flags & 255) == 8;
\r
238 CvFFillSegment* buffer_end = buffer + buffer_size, *head = buffer, *tail = buffer;
\r
240 L = R = XMin = XMax = seed.x;
\r
245 newVal[0] = _newVal[0];
\r
247 img[L] = newVal[0];
\r
249 while( ++R < roi.width && img[R] == val0[0] )
\r
250 img[R] = newVal[0];
\r
252 while( --L >= 0 && img[L] == val0[0] )
\r
253 img[L] = newVal[0];
\r
258 ICV_SET_C3( val0, img + L*3 );
\r
259 ICV_SET_C3( newVal, _newVal );
\r
261 ICV_SET_C3( img + L*3, newVal );
\r
263 while( --L >= 0 && ICV_EQ_C3( img + L*3, val0 ))
\r
264 ICV_SET_C3( img + L*3, newVal );
\r
266 while( ++R < roi.width && ICV_EQ_C3( img + R*3, val0 ))
\r
267 ICV_SET_C3( img + R*3, newVal );
\r
272 ICV_PUSH( seed.y, L, R, R + 1, R, UP );
\r
274 while( head != tail )
\r
276 int k, YC, PL, PR, dir;
\r
277 ICV_POP( YC, L, R, PL, PR, dir );
\r
281 {-dir, L - _8_connectivity, R + _8_connectivity},
\r
282 {dir, L - _8_connectivity, PL - 1},
\r
283 {dir, PR + 1, R + _8_connectivity}
\r
290 if( XMax < R ) XMax = R;
\r
291 if( XMin > L ) XMin = L;
\r
292 if( YMax < YC ) YMax = YC;
\r
293 if( YMin > YC ) YMin = YC;
\r
296 for( k = 0/*(unsigned)(YC - dir) >= (unsigned)roi.height*/; k < 3; k++ )
\r
299 img = pImage + (YC + dir) * step;
\r
300 int left = data[k][1];
\r
301 int right = data[k][2];
\r
303 if( (unsigned)(YC + dir) >= (unsigned)roi.height )
\r
307 for( i = left; i <= right; i++ )
\r
309 if( (unsigned)i < (unsigned)roi.width && img[i] == val0[0] )
\r
312 img[i] = newVal[0];
\r
313 while( --j >= 0 && img[j] == val0[0] )
\r
314 img[j] = newVal[0];
\r
316 while( ++i < roi.width && img[i] == val0[0] )
\r
317 img[i] = newVal[0];
\r
319 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
\r
323 for( i = left; i <= right; i++ )
\r
325 if( (unsigned)i < (unsigned)roi.width && ICV_EQ_C3( img + i*3, val0 ))
\r
328 ICV_SET_C3( img + i*3, newVal );
\r
329 while( --j >= 0 && ICV_EQ_C3( img + j*3, val0 ))
\r
330 ICV_SET_C3( img + j*3, newVal );
\r
332 while( ++i < roi.width && ICV_EQ_C3( img + i*3, val0 ))
\r
333 ICV_SET_C3( img + i*3, newVal );
\r
335 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
\r
343 Cv32suf v0, v1, v2;
\r
344 region->area = area;
\r
345 region->rect.x = XMin;
\r
346 region->rect.y = YMin;
\r
347 region->rect.width = XMax - XMin + 1;
\r
348 region->rect.height = YMax - YMin + 1;
\r
349 v0.i = newVal[0]; v1.i = newVal[1]; v2.i = newVal[2];
\r
350 region->value = cvScalar( v0.f, v1.f, v2.f );
\r
356 /****************************************************************************************\
\r
357 * Gradient Floodfill *
\r
358 \****************************************************************************************/
\r
360 #define DIFF_INT_C1(p1,p2) ((unsigned)((p1)[0] - (p2)[0] + d_lw[0]) <= interval[0])
\r
362 #define DIFF_INT_C3(p1,p2) ((unsigned)((p1)[0] - (p2)[0] + d_lw[0])<= interval[0] && \
\r
363 (unsigned)((p1)[1] - (p2)[1] + d_lw[1])<= interval[1] && \
\r
364 (unsigned)((p1)[2] - (p2)[2] + d_lw[2])<= interval[2])
\r
366 #define DIFF_FLT_C1(p1,p2) (fabs((p1)[0] - (p2)[0] + d_lw[0]) <= interval[0])
\r
368 #define DIFF_FLT_C3(p1,p2) (fabs((p1)[0] - (p2)[0] + d_lw[0]) <= interval[0] && \
\r
369 fabs((p1)[1] - (p2)[1] + d_lw[1]) <= interval[1] && \
\r
370 fabs((p1)[2] - (p2)[2] + d_lw[2]) <= interval[2])
\r
373 icvFloodFill_Grad_8u_CnIR( uchar* pImage, int step, uchar* pMask, int maskStep,
\r
374 CvSize /*roi*/, CvPoint seed, uchar* _newVal, uchar* _d_lw,
\r
375 uchar* _d_up, CvConnectedComp* region, int flags,
\r
376 CvFFillSegment* buffer, int buffer_size, int cn )
\r
378 uchar* img = pImage + step*seed.y;
\r
379 uchar* mask = (pMask += maskStep + 1) + maskStep*seed.y;
\r
382 int sum[] = {0,0,0}, val0[] = {0,0,0};
\r
383 uchar newVal[] = {0,0,0};
\r
384 int d_lw[] = {0,0,0};
\r
385 unsigned interval[] = {0,0,0};
\r
386 int XMin, XMax, YMin = seed.y, YMax = seed.y;
\r
387 int _8_connectivity = (flags & 255) == 8;
\r
388 int fixedRange = flags & CV_FLOODFILL_FIXED_RANGE;
\r
389 int fillImage = (flags & CV_FLOODFILL_MASK_ONLY) == 0;
\r
390 uchar newMaskVal = (uchar)(flags & 0xff00 ? flags >> 8 : 1);
\r
391 CvFFillSegment* buffer_end = buffer + buffer_size, *head = buffer, *tail = buffer;
\r
397 mask[L] = newMaskVal;
\r
399 for( i = 0; i < cn; i++ )
\r
401 newVal[i] = _newVal[i];
\r
402 d_lw[i] = _d_lw[i];
\r
403 interval[i] = (unsigned)(_d_up[i] + _d_lw[i]);
\r
405 val0[i] = img[L*cn+i];
\r
412 while( !mask[R + 1] && DIFF_INT_C1( img + (R+1), val0 ))
\r
413 mask[++R] = newMaskVal;
\r
415 while( !mask[L - 1] && DIFF_INT_C1( img + (L-1), val0 ))
\r
416 mask[--L] = newMaskVal;
\r
420 while( !mask[R + 1] && DIFF_INT_C1( img + (R+1), img + R ))
\r
421 mask[++R] = newMaskVal;
\r
423 while( !mask[L - 1] && DIFF_INT_C1( img + (L-1), img + L ))
\r
424 mask[--L] = newMaskVal;
\r
431 while( !mask[R + 1] && DIFF_INT_C3( img + (R+1)*3, val0 ))
\r
432 mask[++R] = newMaskVal;
\r
434 while( !mask[L - 1] && DIFF_INT_C3( img + (L-1)*3, val0 ))
\r
435 mask[--L] = newMaskVal;
\r
439 while( !mask[R + 1] && DIFF_INT_C3( img + (R+1)*3, img + R*3 ))
\r
440 mask[++R] = newMaskVal;
\r
442 while( !mask[L - 1] && DIFF_INT_C3( img + (L-1)*3, img + L*3 ))
\r
443 mask[--L] = newMaskVal;
\r
449 ICV_PUSH( seed.y, L, R, R + 1, R, UP );
\r
451 while( head != tail )
\r
453 int k, YC, PL, PR, dir, curstep;
\r
454 ICV_POP( YC, L, R, PL, PR, dir );
\r
458 {-dir, L - _8_connectivity, R + _8_connectivity},
\r
459 {dir, L - _8_connectivity, PL - 1},
\r
460 {dir, PR + 1, R + _8_connectivity}
\r
463 unsigned length = (unsigned)(R-L);
\r
467 area += (int)length + 1;
\r
469 if( XMax < R ) XMax = R;
\r
470 if( XMin > L ) XMin = L;
\r
471 if( YMax < YC ) YMax = YC;
\r
472 if( YMin > YC ) YMin = YC;
\r
477 for( k = 0; k < 3; k++ )
\r
480 curstep = dir * step;
\r
481 img = pImage + (YC + dir) * step;
\r
482 mask = pMask + (YC + dir) * maskStep;
\r
483 int left = data[k][1];
\r
484 int right = data[k][2];
\r
487 for( i = left; i <= right; i++ )
\r
489 if( !mask[i] && DIFF_INT_C1( img + i, val0 ))
\r
492 mask[i] = newMaskVal;
\r
493 while( !mask[--j] && DIFF_INT_C1( img + j, val0 ))
\r
494 mask[j] = newMaskVal;
\r
496 while( !mask[++i] && DIFF_INT_C1( img + i, val0 ))
\r
497 mask[i] = newMaskVal;
\r
499 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
\r
502 else if( !_8_connectivity )
\r
503 for( i = left; i <= right; i++ )
\r
505 if( !mask[i] && DIFF_INT_C1( img + i, img - curstep + i ))
\r
508 mask[i] = newMaskVal;
\r
509 while( !mask[--j] && DIFF_INT_C1( img + j, img + (j+1) ))
\r
510 mask[j] = newMaskVal;
\r
512 while( !mask[++i] &&
\r
513 (DIFF_INT_C1( img + i, img + (i-1) ) ||
\r
514 (DIFF_INT_C1( img + i, img + i - curstep) && i <= R)))
\r
515 mask[i] = newMaskVal;
\r
517 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
\r
521 for( i = left; i <= right; i++ )
\r
526 (((val[0] = img[i],
\r
527 (unsigned)(idx = i-L-1) <= length) &&
\r
528 DIFF_INT_C1( val, img - curstep + (i-1))) ||
\r
529 ((unsigned)(++idx) <= length &&
\r
530 DIFF_INT_C1( val, img - curstep + i )) ||
\r
531 ((unsigned)(++idx) <= length &&
\r
532 DIFF_INT_C1( val, img - curstep + (i+1) ))))
\r
535 mask[i] = newMaskVal;
\r
536 while( !mask[--j] && DIFF_INT_C1( img + j, img + (j+1) ))
\r
537 mask[j] = newMaskVal;
\r
539 while( !mask[++i] &&
\r
541 DIFF_INT_C1( val, img + (i-1) )) ||
\r
542 (((unsigned)(idx = i-L-1) <= length &&
\r
543 DIFF_INT_C1( val, img - curstep + (i-1) ))) ||
\r
544 ((unsigned)(++idx) <= length &&
\r
545 DIFF_INT_C1( val, img - curstep + i )) ||
\r
546 ((unsigned)(++idx) <= length &&
\r
547 DIFF_INT_C1( val, img - curstep + (i+1) ))))
\r
548 mask[i] = newMaskVal;
\r
550 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
\r
555 img = pImage + YC * step;
\r
557 for( i = L; i <= R; i++ )
\r
558 img[i] = newVal[0];
\r
560 for( i = L; i <= R; i++ )
\r
565 for( k = 0; k < 3; k++ )
\r
568 curstep = dir * step;
\r
569 img = pImage + (YC + dir) * step;
\r
570 mask = pMask + (YC + dir) * maskStep;
\r
571 int left = data[k][1];
\r
572 int right = data[k][2];
\r
575 for( i = left; i <= right; i++ )
\r
577 if( !mask[i] && DIFF_INT_C3( img + i*3, val0 ))
\r
580 mask[i] = newMaskVal;
\r
581 while( !mask[--j] && DIFF_INT_C3( img + j*3, val0 ))
\r
582 mask[j] = newMaskVal;
\r
584 while( !mask[++i] && DIFF_INT_C3( img + i*3, val0 ))
\r
585 mask[i] = newMaskVal;
\r
587 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
\r
590 else if( !_8_connectivity )
\r
591 for( i = left; i <= right; i++ )
\r
593 if( !mask[i] && DIFF_INT_C3( img + i*3, img - curstep + i*3 ))
\r
596 mask[i] = newMaskVal;
\r
597 while( !mask[--j] && DIFF_INT_C3( img + j*3, img + (j+1)*3 ))
\r
598 mask[j] = newMaskVal;
\r
600 while( !mask[++i] &&
\r
601 (DIFF_INT_C3( img + i*3, img + (i-1)*3 ) ||
\r
602 (DIFF_INT_C3( img + i*3, img + i*3 - curstep) && i <= R)))
\r
603 mask[i] = newMaskVal;
\r
605 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
\r
609 for( i = left; i <= right; i++ )
\r
614 (((ICV_SET_C3( val, img+i*3 ),
\r
615 (unsigned)(idx = i-L-1) <= length) &&
\r
616 DIFF_INT_C3( val, img - curstep + (i-1)*3 )) ||
\r
617 ((unsigned)(++idx) <= length &&
\r
618 DIFF_INT_C3( val, img - curstep + i*3 )) ||
\r
619 ((unsigned)(++idx) <= length &&
\r
620 DIFF_INT_C3( val, img - curstep + (i+1)*3 ))))
\r
623 mask[i] = newMaskVal;
\r
624 while( !mask[--j] && DIFF_INT_C3( img + j*3, img + (j+1)*3 ))
\r
625 mask[j] = newMaskVal;
\r
627 while( !mask[++i] &&
\r
628 ((ICV_SET_C3( val, img + i*3 ),
\r
629 DIFF_INT_C3( val, img + (i-1)*3 )) ||
\r
630 (((unsigned)(idx = i-L-1) <= length &&
\r
631 DIFF_INT_C3( val, img - curstep + (i-1)*3 ))) ||
\r
632 ((unsigned)(++idx) <= length &&
\r
633 DIFF_INT_C3( val, img - curstep + i*3 )) ||
\r
634 ((unsigned)(++idx) <= length &&
\r
635 DIFF_INT_C3( val, img - curstep + (i+1)*3 ))))
\r
636 mask[i] = newMaskVal;
\r
638 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
\r
643 img = pImage + YC * step;
\r
645 for( i = L; i <= R; i++ )
\r
646 ICV_SET_C3( img + i*3, newVal );
\r
648 for( i = L; i <= R; i++ )
\r
650 sum[0] += img[i*3];
\r
651 sum[1] += img[i*3+1];
\r
652 sum[2] += img[i*3+2];
\r
659 region->area = area;
\r
660 region->rect.x = XMin;
\r
661 region->rect.y = YMin;
\r
662 region->rect.width = XMax - XMin + 1;
\r
663 region->rect.height = YMax - YMin + 1;
\r
666 region->value = cvScalar(newVal[0], newVal[1], newVal[2]);
\r
669 double iarea = area ? 1./area : 0;
\r
670 region->value = cvScalar(sum[0]*iarea, sum[1]*iarea, sum[2]*iarea);
\r
679 icvFloodFill_Grad_32f_CnIR( float* pImage, int step, uchar* pMask, int maskStep,
\r
680 CvSize /*roi*/, CvPoint seed, float* _newVal, float* _d_lw,
\r
681 float* _d_up, CvConnectedComp* region, int flags,
\r
682 CvFFillSegment* buffer, int buffer_size, int cn )
\r
684 float* img = pImage + (step /= sizeof(float))*seed.y;
\r
685 uchar* mask = (pMask += maskStep + 1) + maskStep*seed.y;
\r
688 double sum[] = {0,0,0}, val0[] = {0,0,0};
\r
689 float newVal[] = {0,0,0};
\r
690 float d_lw[] = {0,0,0};
\r
691 float interval[] = {0,0,0};
\r
692 int XMin, XMax, YMin = seed.y, YMax = seed.y;
\r
693 int _8_connectivity = (flags & 255) == 8;
\r
694 int fixedRange = flags & CV_FLOODFILL_FIXED_RANGE;
\r
695 int fillImage = (flags & CV_FLOODFILL_MASK_ONLY) == 0;
\r
696 uchar newMaskVal = (uchar)(flags & 0xff00 ? flags >> 8 : 1);
\r
697 CvFFillSegment* buffer_end = buffer + buffer_size, *head = buffer, *tail = buffer;
\r
703 mask[L] = newMaskVal;
\r
705 for( i = 0; i < cn; i++ )
\r
707 newVal[i] = _newVal[i];
\r
708 d_lw[i] = 0.5f*(_d_lw[i] - _d_up[i]);
\r
709 interval[i] = 0.5f*(_d_lw[i] + _d_up[i]);
\r
711 val0[i] = img[L*cn+i];
\r
718 while( !mask[R + 1] && DIFF_FLT_C1( img + (R+1), val0 ))
\r
719 mask[++R] = newMaskVal;
\r
721 while( !mask[L - 1] && DIFF_FLT_C1( img + (L-1), val0 ))
\r
722 mask[--L] = newMaskVal;
\r
726 while( !mask[R + 1] && DIFF_FLT_C1( img + (R+1), img + R ))
\r
727 mask[++R] = newMaskVal;
\r
729 while( !mask[L - 1] && DIFF_FLT_C1( img + (L-1), img + L ))
\r
730 mask[--L] = newMaskVal;
\r
737 while( !mask[R + 1] && DIFF_FLT_C3( img + (R+1)*3, val0 ))
\r
738 mask[++R] = newMaskVal;
\r
740 while( !mask[L - 1] && DIFF_FLT_C3( img + (L-1)*3, val0 ))
\r
741 mask[--L] = newMaskVal;
\r
745 while( !mask[R + 1] && DIFF_FLT_C3( img + (R+1)*3, img + R*3 ))
\r
746 mask[++R] = newMaskVal;
\r
748 while( !mask[L - 1] && DIFF_FLT_C3( img + (L-1)*3, img + L*3 ))
\r
749 mask[--L] = newMaskVal;
\r
755 ICV_PUSH( seed.y, L, R, R + 1, R, UP );
\r
757 while( head != tail )
\r
759 int k, YC, PL, PR, dir, curstep;
\r
760 ICV_POP( YC, L, R, PL, PR, dir );
\r
764 {-dir, L - _8_connectivity, R + _8_connectivity},
\r
765 {dir, L - _8_connectivity, PL - 1},
\r
766 {dir, PR + 1, R + _8_connectivity}
\r
769 unsigned length = (unsigned)(R-L);
\r
773 area += (int)length + 1;
\r
775 if( XMax < R ) XMax = R;
\r
776 if( XMin > L ) XMin = L;
\r
777 if( YMax < YC ) YMax = YC;
\r
778 if( YMin > YC ) YMin = YC;
\r
783 for( k = 0; k < 3; k++ )
\r
786 curstep = dir * step;
\r
787 img = pImage + (YC + dir) * step;
\r
788 mask = pMask + (YC + dir) * maskStep;
\r
789 int left = data[k][1];
\r
790 int right = data[k][2];
\r
793 for( i = left; i <= right; i++ )
\r
795 if( !mask[i] && DIFF_FLT_C1( img + i, val0 ))
\r
798 mask[i] = newMaskVal;
\r
799 while( !mask[--j] && DIFF_FLT_C1( img + j, val0 ))
\r
800 mask[j] = newMaskVal;
\r
802 while( !mask[++i] && DIFF_FLT_C1( img + i, val0 ))
\r
803 mask[i] = newMaskVal;
\r
805 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
\r
808 else if( !_8_connectivity )
\r
809 for( i = left; i <= right; i++ )
\r
811 if( !mask[i] && DIFF_FLT_C1( img + i, img - curstep + i ))
\r
814 mask[i] = newMaskVal;
\r
815 while( !mask[--j] && DIFF_FLT_C1( img + j, img + (j+1) ))
\r
816 mask[j] = newMaskVal;
\r
818 while( !mask[++i] &&
\r
819 (DIFF_FLT_C1( img + i, img + (i-1) ) ||
\r
820 (DIFF_FLT_C1( img + i, img + i - curstep) && i <= R)))
\r
821 mask[i] = newMaskVal;
\r
823 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
\r
827 for( i = left; i <= right; i++ )
\r
833 (((val[0] = img[i],
\r
834 (unsigned)(idx = i-L-1) <= length) &&
\r
835 DIFF_FLT_C1( val, img - curstep + (i-1) )) ||
\r
836 ((unsigned)(++idx) <= length &&
\r
837 DIFF_FLT_C1( val, img - curstep + i )) ||
\r
838 ((unsigned)(++idx) <= length &&
\r
839 DIFF_FLT_C1( val, img - curstep + (i+1) ))))
\r
842 mask[i] = newMaskVal;
\r
843 while( !mask[--j] && DIFF_FLT_C1( img + j, img + (j+1) ))
\r
844 mask[j] = newMaskVal;
\r
846 while( !mask[++i] &&
\r
848 DIFF_FLT_C1( val, img + (i-1) )) ||
\r
849 (((unsigned)(idx = i-L-1) <= length &&
\r
850 DIFF_FLT_C1( val, img - curstep + (i-1) ))) ||
\r
851 ((unsigned)(++idx) <= length &&
\r
852 DIFF_FLT_C1( val, img - curstep + i )) ||
\r
853 ((unsigned)(++idx) <= length &&
\r
854 DIFF_FLT_C1( val, img - curstep + (i+1) ))))
\r
855 mask[i] = newMaskVal;
\r
857 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
\r
862 img = pImage + YC * step;
\r
864 for( i = L; i <= R; i++ )
\r
865 img[i] = newVal[0];
\r
867 for( i = L; i <= R; i++ )
\r
872 for( k = 0; k < 3; k++ )
\r
875 curstep = dir * step;
\r
876 img = pImage + (YC + dir) * step;
\r
877 mask = pMask + (YC + dir) * maskStep;
\r
878 int left = data[k][1];
\r
879 int right = data[k][2];
\r
882 for( i = left; i <= right; i++ )
\r
884 if( !mask[i] && DIFF_FLT_C3( img + i*3, val0 ))
\r
887 mask[i] = newMaskVal;
\r
888 while( !mask[--j] && DIFF_FLT_C3( img + j*3, val0 ))
\r
889 mask[j] = newMaskVal;
\r
891 while( !mask[++i] && DIFF_FLT_C3( img + i*3, val0 ))
\r
892 mask[i] = newMaskVal;
\r
894 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
\r
897 else if( !_8_connectivity )
\r
898 for( i = left; i <= right; i++ )
\r
900 if( !mask[i] && DIFF_FLT_C3( img + i*3, img - curstep + i*3 ))
\r
903 mask[i] = newMaskVal;
\r
904 while( !mask[--j] && DIFF_FLT_C3( img + j*3, img + (j+1)*3 ))
\r
905 mask[j] = newMaskVal;
\r
907 while( !mask[++i] &&
\r
908 (DIFF_FLT_C3( img + i*3, img + (i-1)*3 ) ||
\r
909 (DIFF_FLT_C3( img + i*3, img + i*3 - curstep) && i <= R)))
\r
910 mask[i] = newMaskVal;
\r
912 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
\r
916 for( i = left; i <= right; i++ )
\r
922 (((ICV_SET_C3( val, img+i*3 ),
\r
923 (unsigned)(idx = i-L-1) <= length) &&
\r
924 DIFF_FLT_C3( val, img - curstep + (i-1)*3 )) ||
\r
925 ((unsigned)(++idx) <= length &&
\r
926 DIFF_FLT_C3( val, img - curstep + i*3 )) ||
\r
927 ((unsigned)(++idx) <= length &&
\r
928 DIFF_FLT_C3( val, img - curstep + (i+1)*3 ))))
\r
931 mask[i] = newMaskVal;
\r
932 while( !mask[--j] && DIFF_FLT_C3( img + j*3, img + (j+1)*3 ))
\r
933 mask[j] = newMaskVal;
\r
935 while( !mask[++i] &&
\r
936 ((ICV_SET_C3( val, img + i*3 ),
\r
937 DIFF_FLT_C3( val, img + (i-1)*3 )) ||
\r
938 (((unsigned)(idx = i-L-1) <= length &&
\r
939 DIFF_FLT_C3( val, img - curstep + (i-1)*3 ))) ||
\r
940 ((unsigned)(++idx) <= length &&
\r
941 DIFF_FLT_C3( val, img - curstep + i*3 )) ||
\r
942 ((unsigned)(++idx) <= length &&
\r
943 DIFF_FLT_C3( val, img - curstep + (i+1)*3 ))))
\r
944 mask[i] = newMaskVal;
\r
946 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
\r
951 img = pImage + YC * step;
\r
953 for( i = L; i <= R; i++ )
\r
954 ICV_SET_C3( img + i*3, newVal );
\r
956 for( i = L; i <= R; i++ )
\r
958 sum[0] += img[i*3];
\r
959 sum[1] += img[i*3+1];
\r
960 sum[2] += img[i*3+2];
\r
967 region->area = area;
\r
968 region->rect.x = XMin;
\r
969 region->rect.y = YMin;
\r
970 region->rect.width = XMax - XMin + 1;
\r
971 region->rect.height = YMax - YMin + 1;
\r
974 region->value = cvScalar(newVal[0], newVal[1], newVal[2]);
\r
977 double iarea = area ? 1./area : 0;
\r
978 region->value = cvScalar(sum[0]*iarea, sum[1]*iarea, sum[2]*iarea);
\r
986 /****************************************************************************************\
\r
987 * External Functions *
\r
988 \****************************************************************************************/
\r
990 typedef CvStatus (CV_CDECL* CvFloodFillFunc)(
\r
991 void* img, int step, CvSize size, CvPoint seed, void* newval,
\r
992 CvConnectedComp* comp, int flags, void* buffer, int buffer_size, int cn );
\r
994 typedef CvStatus (CV_CDECL* CvFloodFillGradFunc)(
\r
995 void* img, int step, uchar* mask, int maskStep, CvSize size,
\r
996 CvPoint seed, void* newval, void* d_lw, void* d_up, void* ccomp,
\r
997 int flags, void* buffer, int buffer_size, int cn );
\r
999 static void icvInitFloodFill( void** ffill_tab,
\r
1000 void** ffillgrad_tab )
\r
1002 ffill_tab[0] = (void*)icvFloodFill_8u_CnIR;
\r
1003 ffill_tab[1] = (void*)icvFloodFill_32f_CnIR;
\r
1005 ffillgrad_tab[0] = (void*)icvFloodFill_Grad_8u_CnIR;
\r
1006 ffillgrad_tab[1] = (void*)icvFloodFill_Grad_32f_CnIR;
\r
1011 cvFloodFill( CvArr* arr, CvPoint seed_point,
\r
1012 CvScalar newVal, CvScalar lo_diff, CvScalar up_diff,
\r
1013 CvConnectedComp* comp, int flags, CvArr* maskarr )
\r
1015 static void* ffill_tab[4];
\r
1016 static void* ffillgrad_tab[4];
\r
1017 static int inittab = 0;
\r
1019 CvMat* tempMask = 0;
\r
1020 CvFFillSegment* buffer = 0;
\r
1021 CV_FUNCNAME( "cvFloodFill" );
\r
1024 memset( comp, 0, sizeof(*comp) );
\r
1028 int i, type, depth, cn, is_simple, idx;
\r
1029 int buffer_size, connectivity = flags & 255;
\r
1030 double nv_buf[4] = {0,0,0,0};
\r
1031 union { uchar b[4]; float f[4]; } ld_buf, ud_buf;
\r
1032 CvMat stub, *img = (CvMat*)arr;
\r
1033 CvMat maskstub, *mask = (CvMat*)maskarr;
\r
1038 icvInitFloodFill( ffill_tab, ffillgrad_tab );
\r
1042 CV_CALL( img = cvGetMat( img, &stub ));
\r
1043 type = CV_MAT_TYPE( img->type );
\r
1044 depth = CV_MAT_DEPTH(type);
\r
1045 cn = CV_MAT_CN(type);
\r
1047 idx = type == CV_8UC1 || type == CV_8UC3 ? 0 :
\r
1048 type == CV_32FC1 || type == CV_32FC3 ? 1 : -1;
\r
1051 CV_ERROR( CV_StsUnsupportedFormat, "" );
\r
1053 if( connectivity == 0 )
\r
1055 else if( connectivity != 4 && connectivity != 8 )
\r
1056 CV_ERROR( CV_StsBadFlag, "Connectivity must be 4, 0(=4) or 8" );
\r
1058 is_simple = mask == 0 && (flags & CV_FLOODFILL_MASK_ONLY) == 0;
\r
1060 for( i = 0; i < cn; i++ )
\r
1062 if( lo_diff.val[i] < 0 || up_diff.val[i] < 0 )
\r
1063 CV_ERROR( CV_StsBadArg, "lo_diff and up_diff must be non-negative" );
\r
1064 is_simple &= fabs(lo_diff.val[i]) < DBL_EPSILON && fabs(up_diff.val[i]) < DBL_EPSILON;
\r
1067 size = cvGetMatSize( img );
\r
1069 if( (unsigned)seed_point.x >= (unsigned)size.width ||
\r
1070 (unsigned)seed_point.y >= (unsigned)size.height )
\r
1071 CV_ERROR( CV_StsOutOfRange, "Seed point is outside of image" );
\r
1073 cvScalarToRawData( &newVal, &nv_buf, type, 0 );
\r
1074 buffer_size = MAX( size.width, size.height )*2;
\r
1075 CV_CALL( buffer = (CvFFillSegment*)cvAlloc( buffer_size*sizeof(buffer[0])));
\r
1079 int elem_size = CV_ELEM_SIZE(type);
\r
1080 const uchar* seed_ptr = img->data.ptr + img->step*seed_point.y + elem_size*seed_point.x;
\r
1081 CvFloodFillFunc func = (CvFloodFillFunc)ffill_tab[idx];
\r
1083 CV_ERROR( CV_StsUnsupportedFormat, "" );
\r
1084 // check if the new value is different from the current value at the seed point.
\r
1085 // if they are exactly the same, use the generic version with mask to avoid infinite loops.
\r
1086 for( i = 0; i < elem_size; i++ )
\r
1087 if( seed_ptr[i] != ((uchar*)nv_buf)[i] )
\r
1089 if( i < elem_size )
\r
1091 IPPI_CALL( func( img->data.ptr, img->step, size,
\r
1092 seed_point, &nv_buf, comp, flags,
\r
1093 buffer, buffer_size, cn ));
\r
1099 CvFloodFillGradFunc func = (CvFloodFillGradFunc)ffillgrad_tab[idx];
\r
1101 CV_ERROR( CV_StsUnsupportedFormat, "" );
\r
1105 /* created mask will be 8-byte aligned */
\r
1106 tempMask = cvCreateMat( size.height + 2, (size.width + 9) & -8, CV_8UC1 );
\r
1111 CV_CALL( mask = cvGetMat( mask, &maskstub ));
\r
1112 if( !CV_IS_MASK_ARR( mask ))
\r
1113 CV_ERROR( CV_StsBadMask, "" );
\r
1115 if( mask->width != size.width + 2 || mask->height != size.height + 2 )
\r
1116 CV_ERROR( CV_StsUnmatchedSizes, "mask must be 2 pixel wider "
\r
1117 "and 2 pixel taller than filled image" );
\r
1121 int width = tempMask ? mask->step : size.width + 2;
\r
1122 uchar* mask_row = mask->data.ptr + mask->step;
\r
1123 memset( mask_row - mask->step, 1, width );
\r
1125 for( i = 1; i <= size.height; i++, mask_row += mask->step )
\r
1128 memset( mask_row, 0, width );
\r
1129 mask_row[0] = mask_row[size.width+1] = (uchar)1;
\r
1131 memset( mask_row, 1, width );
\r
1134 if( depth == CV_8U )
\r
1135 for( i = 0; i < cn; i++ )
\r
1137 int t = cvFloor(lo_diff.val[i]);
\r
1138 ld_buf.b[i] = CV_CAST_8U(t);
\r
1139 t = cvFloor(up_diff.val[i]);
\r
1140 ud_buf.b[i] = CV_CAST_8U(t);
\r
1143 for( i = 0; i < cn; i++ )
\r
1145 ld_buf.f[i] = (float)lo_diff.val[i];
\r
1146 ud_buf.f[i] = (float)up_diff.val[i];
\r
1149 IPPI_CALL( func( img->data.ptr, img->step, mask->data.ptr, mask->step,
\r
1150 size, seed_point, &nv_buf, ld_buf.f, ud_buf.f,
\r
1151 comp, flags, buffer, buffer_size, cn ));
\r
1156 cvFree( &buffer );
\r
1157 cvReleaseMat( &tempMask );
\r
1161 int cv::floodFill( Mat& image, Point seedPoint,
\r
1162 Scalar newVal, Rect* rect,
\r
1163 Scalar loDiff, Scalar upDiff, int flags )
\r
1165 CvConnectedComp ccomp;
\r
1166 CvMat _image = image;
\r
1167 cvFloodFill(&_image, seedPoint, newVal, loDiff, upDiff, &ccomp, flags, 0);
\r
1169 *rect = ccomp.rect;
\r
1170 return cvRound(ccomp.area);
\r
1173 int cv::floodFill( Mat& image, Mat& mask,
\r
1174 Point seedPoint, Scalar newVal, Rect* rect,
\r
1175 Scalar loDiff, Scalar upDiff, int flags )
\r
1177 CvConnectedComp ccomp;
\r
1178 CvMat _image = image, _mask = mask;
\r
1179 cvFloodFill(&_image, seedPoint, newVal, loDiff, upDiff, &ccomp, flags, &_mask);
\r
1181 *rect = ccomp.rect;
\r
1182 return cvRound(ccomp.area);
\r
1185 /* End of file. */
\r