示例#1
0
static void
icvFloodFill_CnIR( uchar* pImage, int step, CvSize roi, CvPoint seed,
                   _Tp newVal, CvConnectedComp* region, int flags,
                   std::vector<CvFFillSegment>* buffer )
{
    _Tp* img = (_Tp*)(pImage + step * seed.y);
    int i, L, R;
    int area = 0;
    int XMin, XMax, YMin = seed.y, YMax = seed.y;
    int _8_connectivity = (flags & 255) == 8;
    CvFFillSegment* buffer_end = &buffer->front() + buffer->size(), *head = &buffer->front(), *tail = &buffer->front();

    L = R = XMin = XMax = seed.x;

    _Tp val0 = img[L];
    img[L] = newVal;

    while( ++R < roi.width && img[R] == val0 )
        img[R] = newVal;

    while( --L >= 0 && img[L] == val0 )
        img[L] = newVal;

    XMax = --R;
    XMin = ++L;

    ICV_PUSH( seed.y, L, R, R + 1, R, UP );

    while( head != tail )
    {
        int k, YC, PL, PR, dir;
        ICV_POP( YC, L, R, PL, PR, dir );

        int data[][3] =
        {
            {-dir, L - _8_connectivity, R + _8_connectivity},
            {dir, L - _8_connectivity, PL - 1},
            {dir, PR + 1, R + _8_connectivity}
        };

        if( region )
        {
            area += R - L + 1;

            if( XMax < R ) XMax = R;
            if( XMin > L ) XMin = L;
            if( YMax < YC ) YMax = YC;
            if( YMin > YC ) YMin = YC;
        }

        for( k = 0; k < 3; k++ )
        {
            dir = data[k][0];
            img = (_Tp*)(pImage + (YC + dir) * step);
            int left = data[k][1];
            int right = data[k][2];

            if( (unsigned)(YC + dir) >= (unsigned)roi.height )
                continue;

            for( i = left; i <= right; i++ )
            {
                if( (unsigned)i < (unsigned)roi.width && img[i] == val0 )
                {
                    int j = i;
                    img[i] = newVal;
                    while( --j >= 0 && img[j] == val0 )
                        img[j] = newVal;

                    while( ++i < roi.width && img[i] == val0 )
                        img[i] = newVal;

                    ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
                }
            }
        }
    }

    if( region )
    {
        region->area = area;
        region->rect.x = XMin;
        region->rect.y = YMin;
        region->rect.width = XMax - XMin + 1;
        region->rect.height = YMax - YMin + 1;
        region->value = cv::Scalar(newVal);
    }
}
示例#2
0
static void
icvFloodFillGrad_CnIR( uchar* pImage, int step, uchar* pMask, int maskStep,
                       CvSize /*roi*/, CvPoint seed, _Tp newVal, Diff diff,
                       CvConnectedComp* region, int flags,
                       std::vector<CvFFillSegment>* buffer )
{
    _Tp* img = (_Tp*)(pImage + step*seed.y);
    uchar* mask = (pMask += maskStep + 1) + maskStep*seed.y;
    int i, L, R;
    int area = 0;
    _WTp sum = _WTp((typename cv::DataType<_Tp>::channel_type)0);
    int XMin, XMax, YMin = seed.y, YMax = seed.y;
    int _8_connectivity = (flags & 255) == 8;
    int fixedRange = flags & CV_FLOODFILL_FIXED_RANGE;
    int fillImage = (flags & CV_FLOODFILL_MASK_ONLY) == 0;
    uchar newMaskVal = (uchar)(flags & 0xff00 ? flags >> 8 : 1);
    CvFFillSegment* buffer_end = &buffer->front() + buffer->size(), *head = &buffer->front(), *tail = &buffer->front();

    L = R = seed.x;
    if( mask[L] )
        return;

    mask[L] = newMaskVal;
    _Tp val0 = img[L];

    if( fixedRange )
    {
        while( !mask[R + 1] && diff( img + (R+1), &val0 ))
            mask[++R] = newMaskVal;

        while( !mask[L - 1] && diff( img + (L-1), &val0 ))
            mask[--L] = newMaskVal;
    }
    else
    {
        while( !mask[R + 1] && diff( img + (R+1), img + R ))
            mask[++R] = newMaskVal;

        while( !mask[L - 1] && diff( img + (L-1), img + L ))
            mask[--L] = newMaskVal;
    }

    XMax = R;
    XMin = L;

    ICV_PUSH( seed.y, L, R, R + 1, R, UP );

    while( head != tail )
    {
        int k, YC, PL, PR, dir;
        ICV_POP( YC, L, R, PL, PR, dir );

        int data[][3] =
        {
            {-dir, L - _8_connectivity, R + _8_connectivity},
            {dir, L - _8_connectivity, PL - 1},
            {dir, PR + 1, R + _8_connectivity}
        };

        unsigned length = (unsigned)(R-L);

        if( region )
        {
            area += (int)length + 1;

            if( XMax < R ) XMax = R;
            if( XMin > L ) XMin = L;
            if( YMax < YC ) YMax = YC;
            if( YMin > YC ) YMin = YC;
        }

        for( k = 0; k < 3; k++ )
        {
            dir = data[k][0];
            img = (_Tp*)(pImage + (YC + dir) * step);
            _Tp* img1 = (_Tp*)(pImage + YC * step);
            mask = pMask + (YC + dir) * maskStep;
            int left = data[k][1];
            int right = data[k][2];

            if( fixedRange )
                for( i = left; i <= right; i++ )
                {
                    if( !mask[i] && diff( img + i, &val0 ))
                    {
                        int j = i;
                        mask[i] = newMaskVal;
                        while( !mask[--j] && diff( img + j, &val0 ))
                            mask[j] = newMaskVal;

                        while( !mask[++i] && diff( img + i, &val0 ))
                            mask[i] = newMaskVal;

                        ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
                    }
                }
            else if( !_8_connectivity )
                for( i = left; i <= right; i++ )
                {
                    if( !mask[i] && diff( img + i, img1 + i ))
                    {
                        int j = i;
                        mask[i] = newMaskVal;
                        while( !mask[--j] && diff( img + j, img + (j+1) ))
                            mask[j] = newMaskVal;

                        while( !mask[++i] &&
                               (diff( img + i, img + (i-1) ) ||
                               (diff( img + i, img1 + i) && i <= R)))
                            mask[i] = newMaskVal;

                        ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
                    }
                }
            else
                for( i = left; i <= right; i++ )
                {
                    int idx;
                    _Tp val;

                    if( !mask[i] &&
                        (((val = img[i],
                        (unsigned)(idx = i-L-1) <= length) &&
                        diff( &val, img1 + (i-1))) ||
                        ((unsigned)(++idx) <= length &&
                        diff( &val, img1 + i )) ||
                        ((unsigned)(++idx) <= length &&
                        diff( &val, img1 + (i+1) ))))
                    {
                        int j = i;
                        mask[i] = newMaskVal;
                        while( !mask[--j] && diff( img + j, img + (j+1) ))
                            mask[j] = newMaskVal;

                        while( !mask[++i] &&
                               ((val = img[i],
                               diff( &val, img + (i-1) )) ||
                               (((unsigned)(idx = i-L-1) <= length &&
                               diff( &val, img1 + (i-1) ))) ||
                               ((unsigned)(++idx) <= length &&
                               diff( &val, img1 + i )) ||
                               ((unsigned)(++idx) <= length &&
                               diff( &val, img1 + (i+1) ))))
                            mask[i] = newMaskVal;

                        ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
                    }
                }
        }

        img = (_Tp*)(pImage + YC * step);
        if( fillImage )
            for( i = L; i <= R; i++ )
                img[i] = newVal;
        else if( region )
            for( i = L; i <= R; i++ )
                sum += img[i];
    }

    if( region )
    {
        region->area = area;
        region->rect.x = XMin;
        region->rect.y = YMin;
        region->rect.width = XMax - XMin + 1;
        region->rect.height = YMax - YMin + 1;

        if( fillImage )
            region->value = cv::Scalar(newVal);
        else
        {
            double iarea = area ? 1./area : 0;
            region->value = cv::Scalar(sum*iarea);
        }
    }
}
示例#3
0
static void
icvFloodGrad_CnIR( uchar* idImage, int stepId, uchar* image, int stepY, CvSize roi, CvPoint seed, int newVal,
		CvConnectedComp* region, std::vector<CvFFillSegment>* buffer, long threshold, int maxSize, long (*diff)(const _Tp*, const _Tp*), cv::Mat& segmImg )
{
    int* idImg = (int*)(idImage + stepId * seed.y);
    _Tp* imgPtr = (_Tp*)(image + stepY * seed.y);

    threshold = abs(threshold);

    int i, L, R;
    int area = 0;
    int XMin, XMax, YMin = seed.y, YMax = seed.y;
    int _8_connectivity = 1;
    CvFFillSegment* buffer_end = &buffer->front() + buffer->size(), *head = &buffer->front(), *tail = &buffer->front();

    L = R = XMin = XMax = seed.x;

    idImg[L] = newVal;

    while( (R + 1) < roi.width && idImg[R + 1] != newVal && (diff( imgPtr + (R+1), imgPtr + R ) < threshold))
    	idImg[++R] = newVal;

    while( (L - 1) > 0 && idImg[L - 1]  != newVal && (diff( imgPtr + (L-1), imgPtr + L ) < threshold))
    	idImg[--L] = newVal;

    XMax = R;
    XMin = L;
    assert(R < roi.width);
    ICV_PUSH( seed.y, L, R, R + 1, R, UP );

    while( head != tail )
    {
        int k, YC, PL, PR, dir;
        ICV_POP( YC, L, R, PL, PR, dir );
        int data[][3] =
        {
            {-dir, L - _8_connectivity, R + _8_connectivity},
            {dir, L - _8_connectivity, PL - 1},
            {dir, PR + 1, R + _8_connectivity}
        };

        unsigned length = (unsigned)(R-L);

        if( (unsigned)(YC + dir) >= (unsigned)roi.height )
        	continue;

        if( region )
        {
            if(area > maxSize)
            {
            	region->area = -1;
            	return;
            }
            assert(R < roi.width);
            if( XMax < R ) XMax = R;
            if( XMin > L ) XMin = L;
            assert(XMin >= 0);
            assert(YC < roi.height);
            if( YMax < YC ) YMax = YC;
            if( YMin > YC ) YMin = YC;
            assert(YMin >= 0);
        }

        for( k = 0; k < 3; k++ )
        {
            dir = data[k][0];
            if( (unsigned)(YC + dir) >= (unsigned)roi.height )
            	continue;
            assert((YC + dir) < roi.height);
            assert((YC) < roi.height);
            idImg = (int*)(idImage + (YC + dir) * stepId);
#ifndef NDEBUG
            uchar* simg = segmImg.ptr<uchar>((YC + dir));
#endif
            imgPtr = (_Tp*)(image + stepY * (YC + dir));
            _Tp* img1 = (_Tp*)(image + YC * stepY);

            int left = data[k][1];
            int right = data[k][2];

            if( (unsigned)(YC + dir) >= (unsigned)roi.height )
                continue;

            for( i = left; i <= right; i++ )
            {
            	int idx;
            	_Tp val;

            	if( i >= roi.width )
            		continue;

            	if( idImg[i] != newVal &&
            			(((val = imgPtr[i],
            			(unsigned)(idx = i-L-1) <= length) &&
            			(diff( &val, img1 + (i-1)) < threshold)) ||
            			((unsigned)(++idx) <= length &&
            			(diff( &val, img1 + i ) < threshold)) ||
						((unsigned)(++idx) <= length &&
						(diff( &val, img1 + (i+1) ) < threshold)) ))
            	{
            		int j = i;
            		assert(i < roi.width);
            		idImg[i] = newVal;
#ifndef NDEBUG
            		simg[i] = MAX(150, simg[i]);
#endif
            		area++;
            		while( j > 0 && idImg[--j] != newVal && (diff( imgPtr + j, imgPtr + (j+1) ) < threshold) )
            		{
            			assert(j < (roi.width - 1));
            			idImg[j] = newVal;
#ifndef NDEBUG
            			simg[j] = MAX(150, simg[j]);
#endif
            			area++;
            		}

            		while( ++i <  roi.width && idImg[i] != newVal &&
            				((val = imgPtr[i],
            				diff( &val, imgPtr + (i-1) ) < threshold) ||
            				(((unsigned)(idx = i-L-1) <= length &&
            				diff( &val, img1 + (i-1) ) < threshold)) ||
							((unsigned)(++idx) <= length &&
							diff( &val, img1 + i ) < threshold) ||
							((unsigned)(++idx) <= length &&
							diff( &val, img1 + (i+1) ) < threshold)))
            		{
            			assert(i < roi.width);
            			idImg[i] = newVal;
#ifndef NDEBUG
            			simg[i] = MAX(150, simg[i]);
#endif
            			area++;
            		}
            		assert((i-1) < roi.width);
            		assert(R < roi.width);
            		if(i > 0)
            			ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
            	}
            }
        }
    }

    if( region )
    {
    	//cv::imshow("segm", segmImg);
    	//cv::waitKey(0);

        region->area = area;
        region->rect.x = XMin;
        region->rect.y = YMin;
        region->rect.width = XMax - XMin + 1;
        region->rect.height = YMax - YMin + 1;
        region->value = cv::Scalar(newVal);
    }
}
示例#4
0
static void
icvFloodFill_CnIR( uchar* idImage, int stepId, uchar* image, int stepY, CvSize roi, CvPoint seed, int newVal,
		CvConnectedComp* region, std::vector<CvFFillSegment>* buffer, long threshold, int maxSize, long (*distFunction)(const _Tp&, const _Tp&), cv::Mat& segmImg )
{
    int* idImg = (int*)(idImage + stepId * seed.y);
    _Tp* imgPtr = (_Tp*)(image + stepY * seed.y);
    _Tp& seedPtr = imgPtr[seed.x];

    int i, L, R;
    int area = 0;
    int XMin, XMax, YMin = seed.y, YMax = seed.y;
    int _8_connectivity = 1;
    CvFFillSegment* buffer_end = &buffer->front() + buffer->size(), *head = &buffer->front(), *tail = &buffer->front();

    L = R = XMin = XMax = seed.x;

    idImg[L] = newVal;

    while( ++R < roi.width && distFunction(seedPtr,  imgPtr[R]) <  threshold )
    {
    	idImg[R] = newVal;
    	area++;
    }

    while( --L >= 0 && distFunction(seedPtr,  imgPtr[L]) <  threshold )
    {
    	idImg[L] = newVal;
    	area++;
    }

    XMax = --R;
    XMin = ++L;

    ICV_PUSH( seed.y, L, R, R + 1, R, UP );

    while( head != tail )
    {
        int k, YC, PL, PR, dir;
        ICV_POP( YC, L, R, PL, PR, dir );
        int data[][3] =
        {
            {-dir, L - _8_connectivity, R + _8_connectivity},
            {dir, L - _8_connectivity, PL - 1},
            {dir, PR + 1, R + _8_connectivity}
        };

        if( region )
        {
            if(area > maxSize)
            {
            	region->area = -1;
            	return;
            }

            if( XMax < R ) XMax = R;
            if( XMin > L ) XMin = L;
            if( YMax < YC ) YMax = YC;
            if( YMin > YC ) YMin = YC;
        }

        for( k = 0; k < 3; k++ )
        {
            dir = data[k][0];
            idImg = (int*)(idImage + (YC + dir) * stepId);
            imgPtr = (_Tp*)(image + stepY * (YC + dir));
            int left = data[k][1];
            int right = data[k][2];

            if( (unsigned)(YC + dir) >= (unsigned)roi.height )
                continue;

            for( i = left; i <= right; i++ )
            {
                if( (unsigned)i < (unsigned)roi.width && idImg[i] != newVal && distFunction(seedPtr, imgPtr[i]) <  threshold)
                {
                    int j = i;
                    idImg[i] = newVal;
                    area++;
#ifndef NDEBUG
                    segmImg.at<uchar>((YC + dir), j) = MAX(150, segmImg.at<uchar>((YC + dir), j));
#endif
                    while( --j >= 0 && distFunction(seedPtr, imgPtr[j]) < threshold )
                    {
                    	idImg[j] = newVal;
                    	area++;
#ifndef NDEBUG
                    	segmImg.at<uchar>((YC + dir), j) = MAX(150, segmImg.at<uchar>((YC + dir), j));
#endif
                    }

                    while( ++i < roi.width && distFunction(seedPtr, imgPtr[i]) < threshold)
                    {
                    	idImg[i] = newVal;
                    	area++;
#ifndef NDEBUG
                    	segmImg.at<uchar>((YC + dir), i) = MAX(150, segmImg.at<uchar>((YC + dir), i));
#endif
                    }

                    ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
                }
            }
        }
    }

    if( region )
    {
    	//cv::imshow("segm", segmImg);
    	//cv::waitKey(1);

        region->area = area;
        region->rect.x = XMin;
        region->rect.y = YMin;
        region->rect.width = XMax - XMin + 1;
        region->rect.height = YMax - YMin + 1;
        region->value = cv::Scalar(newVal);
    }
}
示例#5
0
static CvStatus
icvFloodFill_8u_CnIR( uchar* pImage, int step, CvSize roi, CvPoint seed,
                      uchar* _newVal, CvConnectedComp* region, int flags,
                      CvFFillSegment* buffer, int buffer_size, int cn )
{
    uchar* img = pImage + step * seed.y;
    int i, L, R; 
    int area = 0;
    int val0[] = {0,0,0};
    uchar newVal[] = {0,0,0};
    int XMin, XMax, YMin = seed.y, YMax = seed.y;
    int _8_connectivity = (flags & 255) == 8;
    CvFFillSegment* buffer_end = buffer + buffer_size, *head = buffer, *tail = buffer;

    L = R = XMin = XMax = seed.x;

    if( cn == 1 )
    {
        val0[0] = img[L];
        newVal[0] = _newVal[0];

        img[L] = newVal[0];

        while( ++R < roi.width && img[R] == val0[0] )
            img[R] = newVal[0];

        while( --L >= 0 && img[L] == val0[0] )
            img[L] = newVal[0];
    }
    else
    {
        assert( cn == 3 );
        ICV_SET_C3( val0, img + L*3 );
        ICV_SET_C3( newVal, _newVal );
        
        ICV_SET_C3( img + L*3, newVal );
    
        while( --L >= 0 && ICV_EQ_C3( img + L*3, val0 ))
            ICV_SET_C3( img + L*3, newVal );
    
        while( ++R < roi.width && ICV_EQ_C3( img + R*3, val0 ))
            ICV_SET_C3( img + R*3, newVal );
    }

    XMax = --R;
    XMin = ++L;
    ICV_PUSH( seed.y, L, R, R + 1, R, UP );

    while( head != tail )
    {
        int k, YC, PL, PR, dir;
        ICV_POP( YC, L, R, PL, PR, dir );

        int data[][3] =
        {
            {-dir, L - _8_connectivity, R + _8_connectivity},
            {dir, L - _8_connectivity, PL - 1},
            {dir, PR + 1, R + _8_connectivity}
        };

        if( region )
        {
            area += R - L + 1;

            if( XMax < R ) XMax = R;
            if( XMin > L ) XMin = L;
            if( YMax < YC ) YMax = YC;
            if( YMin > YC ) YMin = YC;
        }

        for( k = 0/*(unsigned)(YC - dir) >= (unsigned)roi.height*/; k < 3; k++ )
        {
            dir = data[k][0];
            img = pImage + (YC + dir) * step;
            int left = data[k][1];
            int right = data[k][2];

            if( (unsigned)(YC + dir) >= (unsigned)roi.height )
                continue;

            if( cn == 1 )
                for( i = left; i <= right; i++ )
                {
                    if( (unsigned)i < (unsigned)roi.width && img[i] == val0[0] )
                    {
                        int j = i;
                        img[i] = newVal[0];
                        while( --j >= 0 && img[j] == val0[0] )
                            img[j] = newVal[0];

                        while( ++i < roi.width && img[i] == val0[0] )
                            img[i] = newVal[0];

                        ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
                    }
                }
            else
                for( i = left; i <= right; i++ )
                {
                    if( (unsigned)i < (unsigned)roi.width && ICV_EQ_C3( img + i*3, val0 ))
                    {
                        int j = i;
                        ICV_SET_C3( img + i*3, newVal );
                        while( --j >= 0 && ICV_EQ_C3( img + j*3, val0 ))
                            ICV_SET_C3( img + j*3, newVal );

                        while( ++i < roi.width && ICV_EQ_C3( img + i*3, val0 ))
                            ICV_SET_C3( img + i*3, newVal );

                        ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
                    }
                }
        }
    }

    if( region )
    {
        region->area = area;
        region->rect.x = XMin;
        region->rect.y = YMin;
        region->rect.width = XMax - XMin + 1;
        region->rect.height = YMax - YMin + 1;
        region->value = cvScalar(newVal[0], newVal[1], newVal[2], 0);
    }

    return CV_NO_ERR;
}
示例#6
0
static CvStatus
icvFloodFill_Grad_32f_CnIR( float* pImage, int step, uchar* pMask, int maskStep,
                           CvSize /*roi*/, CvPoint seed, float* _newVal, float* _d_lw,
                           float* _d_up, CvConnectedComp* region, int flags,
                           CvFFillSegment* buffer, int buffer_size, int cn )
{
    float* img = pImage + (step /= sizeof(float))*seed.y;
    uchar* mask = (pMask += maskStep + 1) + maskStep*seed.y;
    int i, L, R;
    int area = 0;
    double sum[] = {0,0,0}, val0[] = {0,0,0};
    float newVal[] = {0,0,0};
    float d_lw[] = {0,0,0};
    float interval[] = {0,0,0};
    int XMin, XMax, YMin = seed.y, YMax = seed.y;
    int _8_connectivity = (flags & 255) == 8;
    int fixedRange = flags & CV_FLOODFILL_FIXED_RANGE;
    int fillImage = (flags & CV_FLOODFILL_MASK_ONLY) == 0;
    uchar newMaskVal = (uchar)(flags & 0xff00 ? flags >> 8 : 1);
    CvFFillSegment* buffer_end = buffer + buffer_size, *head = buffer, *tail = buffer;

    L = R = seed.x;
    if( mask[L] )
        return CV_OK;

    mask[L] = newMaskVal;

    for( i = 0; i < cn; i++ )
    {
        newVal[i] = _newVal[i];
        d_lw[i] = 0.5f*(_d_lw[i] - _d_up[i]);
        interval[i] = 0.5f*(_d_lw[i] + _d_up[i]);
        if( fixedRange )
            val0[i] = img[L*cn+i];
    }

    if( cn == 1 )
    {
        if( fixedRange )
        {
            while( !mask[R + 1] && DIFF_FLT_C1( img + (R+1), val0 ))
                mask[++R] = newMaskVal;

            while( !mask[L - 1] && DIFF_FLT_C1( img + (L-1), val0 ))
                mask[--L] = newMaskVal;
        }
        else
        {
            while( !mask[R + 1] && DIFF_FLT_C1( img + (R+1), img + R ))
                mask[++R] = newMaskVal;

            while( !mask[L - 1] && DIFF_FLT_C1( img + (L-1), img + L ))
                mask[--L] = newMaskVal;
        }
    }
    else
    {
        if( fixedRange )
        {
            while( !mask[R + 1] && DIFF_FLT_C3( img + (R+1)*3, val0 ))
                mask[++R] = newMaskVal;

            while( !mask[L - 1] && DIFF_FLT_C3( img + (L-1)*3, val0 ))
                mask[--L] = newMaskVal;
        }
        else
        {
            while( !mask[R + 1] && DIFF_FLT_C3( img + (R+1)*3, img + R*3 ))
                mask[++R] = newMaskVal;

            while( !mask[L - 1] && DIFF_FLT_C3( img + (L-1)*3, img + L*3 ))
                mask[--L] = newMaskVal;
        }
    }

    XMax = R;
    XMin = L;
    ICV_PUSH( seed.y, L, R, R + 1, R, UP );

    while( head != tail )
    {
        int k, YC, PL, PR, dir, curstep;
        ICV_POP( YC, L, R, PL, PR, dir );

        int data[][3] =
        {
            {-dir, L - _8_connectivity, R + _8_connectivity},
            {dir, L - _8_connectivity, PL - 1},
            {dir, PR + 1, R + _8_connectivity}
        };

        unsigned length = (unsigned)(R-L);

        if( region )
        {
            area += (int)length + 1;

            if( XMax < R ) XMax = R;
            if( XMin > L ) XMin = L;
            if( YMax < YC ) YMax = YC;
            if( YMin > YC ) YMin = YC;
        }

        if( cn == 1 )
        {
            for( k = 0; k < 3; k++ )
            {
                dir = data[k][0];
                curstep = dir * step;
                img = pImage + (YC + dir) * step;
                mask = pMask + (YC + dir) * maskStep;
                int left = data[k][1];
                int right = data[k][2];

                if( fixedRange )
                    for( i = left; i <= right; i++ )
                    {
                        if( !mask[i] && DIFF_FLT_C1( img + i, val0 ))
                        {
                            int j = i;
                            mask[i] = newMaskVal;
                            while( !mask[--j] && DIFF_FLT_C1( img + j, val0 ))
                                mask[j] = newMaskVal;

                            while( !mask[++i] && DIFF_FLT_C1( img + i, val0 ))
                                mask[i] = newMaskVal;

                            ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
                        }
                    }
                else if( !_8_connectivity )
                    for( i = left; i <= right; i++ )
                    {
                        if( !mask[i] && DIFF_FLT_C1( img + i, img - curstep + i ))
                        {
                            int j = i;
                            mask[i] = newMaskVal;
                            while( !mask[--j] && DIFF_FLT_C1( img + j, img + (j+1) ))
                                mask[j] = newMaskVal;

                            while( !mask[++i] &&
                                   (DIFF_FLT_C1( img + i, img + (i-1) ) ||
                                   (DIFF_FLT_C1( img + i, img + i - curstep) && i <= R)))
                                mask[i] = newMaskVal;

                            ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
                        }
                    }
                else
                    for( i = left; i <= right; i++ )
                    {
                        int idx;
                        float val[1];
                
                        if( !mask[i] &&
                            ((val[0] = img[i],
                            (unsigned)(idx = i-L-1) <= length) &&
                            DIFF_FLT_C1( val, img - curstep + (i-1) ) ||
                            (unsigned)(++idx) <= length &&
                            DIFF_FLT_C1( val, img - curstep + i ) ||
                            (unsigned)(++idx) <= length &&
                            DIFF_FLT_C1( val, img - curstep + (i+1) )))
                        {
                            int j = i;
                            mask[i] = newMaskVal;
                            while( !mask[--j] && DIFF_FLT_C1( img + j, img + (j+1) ))
                                mask[j] = newMaskVal;

                            while( !mask[++i] &&
                                   ((val[0] = img[i],
                                   DIFF_FLT_C1( val, img + (i-1) )) ||
                                   ((unsigned)(idx = i-L-1) <= length &&
                                   DIFF_FLT_C1( val, img - curstep + (i-1) )) ||
                                   (unsigned)(++idx) <= length &&
                                   DIFF_FLT_C1( val, img - curstep + i ) ||
                                   (unsigned)(++idx) <= length &&
                                   DIFF_FLT_C1( val, img - curstep + (i+1) )))
                                mask[i] = newMaskVal;

                            ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
                        }
                    }
            }

            img = pImage + YC * step;
            if( fillImage )
                for( i = L; i <= R; i++ )
                    img[i] = newVal[0];
            else if( region )
                for( i = L; i <= R; i++ )
                    sum[0] += img[i];
        }
        else
        {
            for( k = 0; k < 3; k++ )
            {
                dir = data[k][0];
                curstep = dir * step;
                img = pImage + (YC + dir) * step;
                mask = pMask + (YC + dir) * maskStep;
                int left = data[k][1];
                int right = data[k][2];

                if( fixedRange )
                    for( i = left; i <= right; i++ )
                    {
                        if( !mask[i] && DIFF_FLT_C3( img + i*3, val0 ))
                        {
                            int j = i;
                            mask[i] = newMaskVal;
                            while( !mask[--j] && DIFF_FLT_C3( img + j*3, val0 ))
                                mask[j] = newMaskVal;

                            while( !mask[++i] && DIFF_FLT_C3( img + i*3, val0 ))
                                mask[i] = newMaskVal;

                            ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
                        }
                    }
                else if( !_8_connectivity )
                    for( i = left; i <= right; i++ )
                    {
                        if( !mask[i] && DIFF_FLT_C3( img + i*3, img - curstep + i*3 ))
                        {
                            int j = i;
                            mask[i] = newMaskVal;
                            while( !mask[--j] && DIFF_FLT_C3( img + j*3, img + (j+1)*3 ))
                                mask[j] = newMaskVal;

                            while( !mask[++i] &&
                                   (DIFF_FLT_C3( img + i*3, img + (i-1)*3 ) ||
                                   (DIFF_FLT_C3( img + i*3, img + i*3 - curstep) && i <= R)))
                                mask[i] = newMaskVal;

                            ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
                        }
                    }
                else
                    for( i = left; i <= right; i++ )
                    {
                        int idx;
                        float val[3];
                
                        if( !mask[i] &&
                            ((ICV_SET_C3( val, img+i*3 ),
                            (unsigned)(idx = i-L-1) <= length) &&
                            DIFF_FLT_C3( val, img - curstep + (i-1)*3 ) ||
                            (unsigned)(++idx) <= length &&
                            DIFF_FLT_C3( val, img - curstep + i*3 ) ||
                            (unsigned)(++idx) <= length &&
                            DIFF_FLT_C3( val, img - curstep + (i+1)*3 )))
                        {
                            int j = i;
                            mask[i] = newMaskVal;
                            while( !mask[--j] && DIFF_FLT_C3( img + j*3, img + (j+1)*3 ))
                                mask[j] = newMaskVal;

                            while( !mask[++i] &&
                                   ((ICV_SET_C3( val, img + i*3 ),
                                   DIFF_FLT_C3( val, img + (i-1)*3 )) ||
                                   ((unsigned)(idx = i-L-1) <= length &&
                                   DIFF_FLT_C3( val, img - curstep + (i-1)*3 )) ||
                                   (unsigned)(++idx) <= length &&
                                   DIFF_FLT_C3( val, img - curstep + i*3 ) ||
                                   (unsigned)(++idx) <= length &&
                                   DIFF_FLT_C3( val, img - curstep + (i+1)*3 )))
                                mask[i] = newMaskVal;

                            ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
                        }
                    }
            }

            img = pImage + YC * step;
            if( fillImage )
                for( i = L; i <= R; i++ )
                    ICV_SET_C3( img + i*3, newVal );
            else if( region )
                for( i = L; i <= R; i++ )
                {
                    sum[0] += img[i*3];
                    sum[1] += img[i*3+1];
                    sum[2] += img[i*3+2];
                }
        }
    }
    
    if( region )
    {
        region->area = area;
        region->rect.x = XMin;
        region->rect.y = YMin;
        region->rect.width = XMax - XMin + 1;
        region->rect.height = YMax - YMin + 1;
    
        if( fillImage )
            region->value = cvScalar(newVal[0], newVal[1], newVal[2]);
        else
        {
            double iarea = area ? 1./area : 0;
            region->value = cvScalar(sum[0]*iarea, sum[1]*iarea, sum[2]*iarea);
        }
    }

    return CV_NO_ERR;
}