51 #include <opencv2/opencv.hpp>
52 #include <opencv2/core/types_c.h>
53 #include <opencv2/imgproc/imgproc_c.h>
56 #define __BEGIN__ __CV_BEGIN__
60 #define __END__ __CV_END__
64 #define EXIT __CV_EXIT__
67 typedef struct CvFFillSegment
81 #define ICV_PUSH( Y, L, R, PREV_L, PREV_R, DIR )\
83 tail->y = (ushort)(Y); \
84 tail->l = (ushort)(L); \
85 tail->r = (ushort)(R); \
86 tail->prevl = (ushort)(PREV_L); \
87 tail->prevr = (ushort)(PREV_R); \
88 tail->dir = (short)(DIR); \
89 if( ++tail >= buffer_end ) \
94 #define ICV_POP( Y, L, R, PREV_L, PREV_R, DIR ) \
99 PREV_L = head->prevl; \
100 PREV_R = head->prevr; \
102 if( ++head >= buffer_end ) \
106 #define DIFF_FLT_C1(p1,p2) (fabs((p1)[0] - (p2)[0] + d_lw[0]) <= interval[0])
109 icvFloodFill_Grad_32f_CnIR2(
float* pImage,
int step, uchar* pMask,
int maskStep,
110 CvSize , CvPoint seed,
float* _newVal,
float* _d_lw,
111 float* _d_up, CvConnectedComp* region,
int flags,
112 CvFFillSegment* buffer,
int buffer_size,
int cn )
114 float* img = pImage + (step /=
sizeof(float))*seed.y;
115 uchar* mask = (pMask += maskStep + 1) + maskStep*seed.y;
118 double sum[] = {0,0,0}, val0[] = {0,0,0};
119 float newVal[] = {0,0,0};
120 float d_lw[] = {0,0,0};
121 float interval[] = {0,0,0};
122 int XMin, XMax, YMin = seed.y, YMax = seed.y;
123 int _8_connectivity = (flags & 255) == 8;
124 int fixedRange = flags & CV_FLOODFILL_FIXED_RANGE;
125 int fillImage = (flags & CV_FLOODFILL_MASK_ONLY) == 0;
126 uchar newMaskVal = (uchar)(flags & 0xff00 ? flags >> 8 : 1);
127 CvFFillSegment* buffer_end = buffer + buffer_size, *head = buffer, *tail = buffer;
130 double varAdaptA=0, varAdaptB=0;
132 double varAdaptAlpha=0.9;
133 double varAdaptK=0.5;
134 double varAdaptKa=1.5;
135 double varAdapt_aux=0;
143 mask[L] = newMaskVal;
145 for( i = 0; i < cn; i++ )
147 newVal[i] = _newVal[i];
148 d_lw[i] = 0.5f*(_d_lw[i] - _d_up[i]);
149 interval[i] = 0.5f*(_d_lw[i] + _d_up[i]);
151 val0[i] = img[L*cn+i];
158 while( !mask[R + 1] && DIFF_FLT_C1( img + (R+1), val0 )){
161 varAdapt_aux = (img+ R+1)[0];
162 varAdaptA += varAdapt_aux;
163 varAdaptB += varAdapt_aux*varAdapt_aux;
166 varAdapt_aux = sqrt( varAdaptB/varAdaptN - (varAdaptA*varAdaptA/(varAdaptN*varAdaptN)) );
167 varAdapt_aux = val0[0] - (varAdaptA/varAdaptN)*( 1+varAdaptK*((varAdapt_aux/128)-1) );
168 interval[0] = (float)(varAdaptAlpha*interval[0] + (1-varAdaptAlpha)*varAdapt_aux);
172 mask[++R] = newMaskVal;
176 while( !mask[L - 1] && DIFF_FLT_C1( img + (L-1), val0 )){
179 varAdapt_aux = (img+ L-1)[0];
180 varAdaptA += varAdapt_aux;
181 varAdaptB += varAdapt_aux*varAdapt_aux;
184 varAdapt_aux = sqrt( varAdaptB/varAdaptN - (varAdaptA*varAdaptA/(varAdaptN*varAdaptN)) );
185 varAdapt_aux = val0[0] - (varAdaptA/varAdaptN)*( 1+varAdaptK*((varAdapt_aux/128)-1) );
186 interval[0] = (float)(varAdaptAlpha*interval[0] + (1-varAdaptAlpha)*varAdapt_aux);
190 mask[--L] = newMaskVal;
196 while( !mask[R + 1] && DIFF_FLT_C1( img + (R+1), img + R ))
197 mask[++R] = newMaskVal;
199 while( !mask[L - 1] && DIFF_FLT_C1( img + (L-1), img + L ))
200 mask[--L] = newMaskVal;
206 ICV_PUSH( seed.y, L, R, R + 1, R, UP );
208 while( head != tail )
210 int k, YC, PL, PR, dir, curstep;
211 ICV_POP( YC, L, R, PL, PR, dir );
215 {-dir, L - _8_connectivity, R + _8_connectivity},
216 {dir, L - _8_connectivity, PL - 1},
217 {dir, PR + 1, R + _8_connectivity}
220 unsigned length = (unsigned)(R-L);
224 area += (int)length + 1;
226 if( XMax < R ) XMax = R;
227 if( XMin > L ) XMin = L;
228 if( YMax < YC ) YMax = YC;
229 if( YMin > YC ) YMin = YC;
234 for( k = 0; k < 3; k++ )
237 curstep = dir * step;
238 img = pImage + (YC + dir) * step;
239 mask = pMask + (YC + dir) * maskStep;
240 int left = data[k][1];
241 int right = data[k][2];
246 for( i = left; i <= right; i++ )
248 if( !mask[i] && DIFF_FLT_C1( img + i, val0 ))
251 mask[i] = newMaskVal;
252 while( !mask[--j] && DIFF_FLT_C1( img + j, val0 )){
253 mask[j] = newMaskVal;
254 varAdapt_aux = (img+j)[0];
255 varAdaptA += varAdapt_aux;
256 varAdaptB += varAdapt_aux*varAdapt_aux;
259 varAdapt_aux = sqrt( varAdaptB/varAdaptN - (varAdaptA*varAdaptA/(varAdaptN*varAdaptN)) );
260 varAdapt_aux = val0[0] - (varAdaptA/varAdaptN)*( 1+varAdaptK*((varAdapt_aux/128)-1) );
261 interval[0] = (float)(varAdaptAlpha*interval[0] + (1-varAdaptAlpha)*varAdapt_aux);
267 while( !mask[++i] && DIFF_FLT_C1( img + i, val0 )){
268 mask[i] = newMaskVal;
269 varAdapt_aux = (img+i)[0];
270 varAdaptA += varAdapt_aux;
271 varAdaptB += varAdapt_aux*varAdapt_aux;
274 varAdapt_aux = sqrt( varAdaptB/varAdaptN - (varAdaptA*varAdaptA/(varAdaptN*varAdaptN)) );
275 varAdapt_aux = val0[0] - (varAdaptA/varAdaptN)*( 1+varAdaptK*((varAdapt_aux/128)-1) );
276 interval[0] = (float)(varAdaptAlpha*interval[0] + (1-varAdaptAlpha)*varAdapt_aux);
282 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
286 else if( !_8_connectivity )
287 for( i = left; i <= right; i++ )
289 if( !mask[i] && DIFF_FLT_C1( img + i, img - curstep + i ))
292 mask[i] = newMaskVal;
293 while( !mask[--j] && DIFF_FLT_C1( img + j, img + (j+1) ))
294 mask[j] = newMaskVal;
297 (DIFF_FLT_C1( img + i, img + (i-1) ) ||
298 (DIFF_FLT_C1( img + i, img + i - curstep) && i <= R)))
299 mask[i] = newMaskVal;
301 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
305 for( i = left; i <= right; i++ )
312 (
unsigned)(idx = i-L-1) <= length) &&
313 DIFF_FLT_C1( val, img - curstep + (i-1) )) ||
314 ((
unsigned)(++idx) <= length &&
315 DIFF_FLT_C1( val, img - curstep + i )) ||
316 ((
unsigned)(++idx) <= length &&
317 DIFF_FLT_C1( val, img - curstep + (i+1) ))))
320 mask[i] = newMaskVal;
321 while( !mask[--j] && DIFF_FLT_C1( img + j, img + (j+1) ))
322 mask[j] = newMaskVal;
326 DIFF_FLT_C1( val, img + (i-1) )) ||
327 (((
unsigned)(idx = i-L-1) <= length &&
328 DIFF_FLT_C1( val, img - curstep + (i-1) ))) ||
329 ((
unsigned)(++idx) <= length &&
330 DIFF_FLT_C1( val, img - curstep + i )) ||
331 ((
unsigned)(++idx) <= length &&
332 DIFF_FLT_C1( val, img - curstep + (i+1) ))))
333 mask[i] = newMaskVal;
335 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
340 img = pImage + YC * step;
342 for( i = L; i <= R; i++ )
345 for( i = L; i <= R; i++ )
353 region->rect.x = XMin;
354 region->rect.y = YMin;
355 region->rect.width = XMax - XMin + 1;
356 region->rect.height = YMax - YMin + 1;
359 region->value = cvScalar(newVal[0], newVal[1], newVal[2]);
362 double iarea = area ? 1./area : 0;
363 region->value = cvScalar(sum[0]*iarea, sum[1]*iarea, sum[2]*iarea);
373 typedef void (*CvFloodFillFunc2)(
374 void* img,
int step, CvSize size, CvPoint seed,
void* newval,
375 CvConnectedComp* comp,
int flags,
void* buffer,
int buffer_size,
int cn );
377 typedef void (*CvFloodFillGradFunc2)(
378 void* img,
int step, uchar* mask,
int maskStep, CvSize size,
379 CvPoint seed,
void* newval,
void* d_lw,
void* d_up,
void* ccomp,
380 int flags,
void* buffer,
int buffer_size,
int cn );
383 static void icvInitFloodFill(
void** ffill_tab,
void** ffillgrad_tab )
388 ffillgrad_tab[0] = NULL;
389 ffillgrad_tab[1] = (
void*)icvFloodFill_Grad_32f_CnIR2;
394 cvFloodFill2( CvArr* arr, CvPoint seed_point,
395 CvScalar newVal, CvScalar lo_diff, CvScalar up_diff,
396 CvConnectedComp* comp,
int flags, CvArr* maskarr )
398 static void* ffill_tab[4];
399 static void* ffillgrad_tab[4];
400 static int inittab = 0;
403 CvFFillSegment* buffer = 0;
404 CV_FUNCNAME(
"cvFloodFill" );
407 memset( comp, 0,
sizeof(*comp) );
411 int i, type, depth, cn, is_simple, idx;
412 int buffer_size, connectivity = flags & 255;
413 double nv_buf[4] = {0,0,0,0};
414 union { uchar b[4];
float f[4]; } ld_buf, ud_buf;
415 CvMat stub, *img = (CvMat*)arr;
416 CvMat maskstub, *mask = (CvMat*)maskarr;
421 icvInitFloodFill( ffill_tab, ffillgrad_tab );
425 CV_CALL( img = cvGetMat( img, &stub ));
426 type = CV_MAT_TYPE( img->type );
427 depth = CV_MAT_DEPTH(type);
428 cn = CV_MAT_CN(type);
430 idx = type == CV_8UC1 || type == CV_8UC3 ? 0 :
431 type == CV_32FC1 || type == CV_32FC3 ? 1 : -1;
434 CV_ERROR( CV_StsUnsupportedFormat,
"" );
436 if( connectivity == 0 )
438 else if( connectivity != 4 && connectivity != 8 )
439 CV_ERROR( CV_StsBadFlag,
"Connectivity must be 4, 0(=4) or 8" );
441 is_simple = mask == 0 && (flags & CV_FLOODFILL_MASK_ONLY) == 0;
443 for( i = 0; i < cn; i++ )
445 if( lo_diff.val[i] < 0 || up_diff.val[i] < 0 )
446 CV_ERROR( CV_StsBadArg,
"lo_diff and up_diff must be non-negative" );
447 is_simple &= fabs(lo_diff.val[i]) < DBL_EPSILON && fabs(up_diff.val[i]) < DBL_EPSILON;
450 if( (
unsigned)seed_point.x >= (
unsigned)size.width ||
451 (
unsigned)seed_point.y >= (
unsigned)size.height )
452 CV_ERROR( CV_StsOutOfRange,
"Seed point is outside of image" );
454 cvScalarToRawData( &newVal, &nv_buf, type, 0 );
455 buffer_size = MAX( size.width, size.height )*2;
456 CV_CALL( buffer = (CvFFillSegment*)cvAlloc( buffer_size*
sizeof(buffer[0])));
460 int elem_size = CV_ELEM_SIZE(type);
461 const uchar* seed_ptr = img->data.ptr + img->step*seed_point.y + elem_size*seed_point.x;
462 CvFloodFillFunc2 func = (CvFloodFillFunc2)ffill_tab[idx];
464 CV_ERROR( CV_StsUnsupportedFormat,
"" );
467 for( i = 0; i < elem_size; i++ )
468 if( seed_ptr[i] != ((uchar*)nv_buf)[i] )
472 func( img->data.ptr, img->step, size,
473 seed_point, &nv_buf, comp, flags,
474 buffer, buffer_size, cn );
480 CvFloodFillGradFunc2 func = (CvFloodFillGradFunc2)ffillgrad_tab[idx];
482 CV_ERROR( CV_StsUnsupportedFormat,
"" );
487 tempMask = cvCreateMat( size.height + 2, (size.width + 9) & -8, CV_8UC1 );
492 CV_CALL( mask = cvGetMat( mask, &maskstub ));
493 if( !CV_IS_MASK_ARR( mask ))
494 CV_ERROR( CV_StsBadMask,
"" );
496 if( mask->width != size.width + 2 || mask->height != size.height + 2 )
497 CV_ERROR( CV_StsUnmatchedSizes,
"mask must be 2 pixel wider "
498 "and 2 pixel taller than filled image" );
502 int width = tempMask ? mask->step : size.width + 2;
503 uchar* mask_row = mask->data.ptr + mask->step;
504 memset( mask_row - mask->step, 1, width );
506 for( i = 1; i <= size.height; i++, mask_row += mask->step )
509 memset( mask_row, 0, width );
510 mask_row[0] = mask_row[size.width+1] = (uchar)1;
512 memset( mask_row, 1, width );
516 for( i = 0; i < cn; i++ )
518 ld_buf.b[i] = cv::saturate_cast<uchar>(cvFloor(lo_diff.val[i]));
519 ud_buf.b[i] = cv::saturate_cast<uchar>(cvFloor(up_diff.val[i]));
522 for( i = 0; i < cn; i++ )
524 ld_buf.f[i] = (float)lo_diff.val[i];
525 ud_buf.f[i] = (
float)up_diff.val[i];
528 func( img->data.ptr, img->step, mask->data.ptr, mask->step,
529 size, seed_point, &nv_buf, ld_buf.f, ud_buf.f,
530 comp, flags, buffer, buffer_size, cn );
536 cvReleaseMat( &tempMask );