Flood Fill(漫水填充)算法

Floodfill算法即漫水填充法,是区域填充法的一种,其实质是种子填充法,这种方法适用于对内定义区域的填充。
所谓内定义区域,是指区域内部所有像素具有同一颜色或亮度值,而区域外的所有像素具有另一种颜色或亮度值。Floodfill方法能将该区域中的全部像素都设置为新值,并通过一定的规则确定一组种子点(该种子点为区域内点),然后通过判断种子点的邻域像素是否和种子构成连通域,从而决定是否对其进行填充,直到找到区域内所有像素或达到轮廓线的边界。

Floodfill是一个非常有用的功能,经常被用来标记和分离图像的一部分以便对其进行进一步处理和分析。漫水填充也可以用来对输入图像获取掩码区域,掩码会加速处理过程,或只处理掩码指定的像素点。


在OpenCV中有一个函数floodfill()可以直接实现漫水填充的功能。它的声明如下:

C++:  int  floodFill (InputOutputArray  image, Point  seedPoint, Scalar  newVal, Rect*  rect=0, Scalar  loDiff=Scalar(), Scalar  upDiff=Scalar(), int  flags=4  ) ¶
C++:  int  floodFill (InputOutputArray  image, InputOutputArray  mask, Point  seedPoint, Scalar  newVal, Rect*  rect=0, Scalar  loDiff=Scalar(), Scalar  upDiff=Scalar(), int  flags=4  )
在上面的floodfill函数中,第二个函数包含掩码参数,用来控制哪些区域将被填充颜色。

image是输入图像,该图像可以是8位或浮点型的单通道或者三通道图像。漫水填充法从点seedPoint开始,newVal是像素点被染色的值。如果一个像素点的值不低于被染色的相邻点减去loDiff且不高于其加上upDiff,那么该像素点就会被染色。如果flags参数包含CV_FLOODFILL_FIXED_RANGE,这时每个像素点都将与种子点而不是相邻点相比较。如果rect不是NULL,那么其将被设置为填充区域的统计属性。

这里面mask参数所代表的掩码既可以作为floodfill()函数的输入值(此时它控制可以被填充的区域),也可以作为floodfill()函数的输出值(此时它指已被填充的区域)。如果mask非空,那么它必须是一个单通道、8位、像素宽度和高度均比原图像大两倍的图像(这是为了使内部运算更简单快速)。mask图像的像素(x+1,y+1)与原图像的像素(x,y)相对应。

Note:

floodfill()不会覆盖mask的非0像素点,因此如果不希望mask阻碍填充操作,将其中元素设为0。

如果mask不为空,那么要用flags参数的中间比特值(第8~15位)来填充掩码图像。如果没有设置flags中间比特值,则取默认值1.如果填充了掩码后显示出来的黑色,不要感到奇怪,因为所设置的值(如果flags的中间没有没设置)为1,所以如果要显示它,必须需要放大这个掩码图像的数值。


下面讲一下flags参数。此参数包含三部分:

低8位部分(第0~7位)可以设为4或8,这个参数控制填充算法的连通性。如果设为4,填充算法只考虑当前像素水平方向和垂直方向的相邻点;如果设为8,除上述点外,还要考虑对角线方向的点。

高8位部分(第16~23位)可以设为CV_FLOODFILL_FIXED_RANGE(如果设置为这个值,则只有当某个相邻点与种子像素之间的差值在指定范围内才填充)或者CV_FLOODFILL_MASK_ONLY(如果设置,函数不填充原始图像,而去填充掩码图像)。很明显,如果设置CV_FLOODFILL_MASK_ONLY,必须输入符合要求的掩码。

中间8位(第8~15位)的值指定填充掩码图像的值。但如果中间比特值为0,则掩码用1填充。

所有flags可以通过OR操作连接起来。例如,如果想用8邻域填充,并填充固定像素值范围,是填充掩码而不是填充原图像,以及设置填充值为47,那么输入的参数应该是:

flags = 8
          | CV_FLOODFILL_MASK_ONLY
          | CV_FLOODFILL_FIXED_RANGE
          | (47<<8)




你可能感兴趣的:(floodfill)