3.4 案例9:使用漫水填充
漫水填充算法是填充算法中最常见的一种,就是将图像中与注水点连通的区域填充为指定的颜色,在图像分割中有重要的作用。该算法的实现过程分为以下三个步骤:
(1)选择一个注水点,这个点就是用户想要将其填充为指定颜色的点。
(2)以这个注水点为中心,在它的4邻域或8邻域中寻找满足条件的像素点,条件是目标像素点的像素值与该点像素值的差值在一定的范围内,该范围就是指定的下限和上限之间。
(3)将邻域中符合条件的像素点作为新的注水点,反复操作步骤(2),直到没有新的像素点可以被指定为注水点。
OpenCV提供了漫水填充操作的函数floodFill()。
C++版本对应的函数如下:
C++版本另一个重载的函数如下:
两个函数的差异是第二个函数多了一个参数InputOutputArray mask,其他的参数都是完全一样的。
Python版本对应的函数如下:
floodFill函数对应的参数及其含义如表3.11所示。
表3.11
续表
表3.11中的参数含义补充说明如下:
mask 用于标记哪些区域会被应用填充算法,mask 像素值为0的区域会被应用填充算法,而不为0的区域则不会被应用填充算法。
注意:mask的尺寸需要比操作的图像的尺寸大2个像素,若被操作的图像的尺寸为(w, h),则mask的尺寸为(w+2, h+2),否则函数调用会报错。
flags操作符标志包含三个部分:低八位(0~8)用来设置选择4邻域或8邻域;中间八位(8~16)包含一个1~255的值,用来填充掩模(默认值为1);高八位通过FloodFillFlags的两个枚举值控制操作。
FloodFillFlags函数对应的参数及其含义如表3.12所示。
表3.12
所有的标志位可以通过按位或“|”运算连接。例如,使用8连通域,并且只填充mask,填充值为255,设置这个标志位如下:
下面通过案例来展示漫水填充的使用效果。这里使用一张优美的城市夜景作为案例的源图像,如图3.22所示。
图3.22
应用漫水填充算法的代码如下:
在本次操作中,选择的注水点是坐标值为(1100,800)的点,被操作的图像copy_img在执行填充算法后被填充为黑色,像素的差值的下限为(30,30,30),上限为(40,40,40)。填充后的图像结果如图3.23所示。
图3.23
可以通过mask控制执行填充算法的区域,mask填充为0的区域才会执行填充算法,接下来对图像的右边部分执行漫水填充,代码如下:
在创建mask1时全部赋值为1,此时整个输入图像区域均会执行填充算法。本案例源图像的尺寸为2000×1125,执行mask1[:,1000:]=0就是将图片从位置1000到最右边均赋值为0,因而图像左边区域不执行填充算法,只有右边区域执行填充算法,效果如图3.24所示。
图3.24
对比图3.23可以看到,只有图像的右边区域执行了填充算法。
接下来在执行填充算法前,添加标志flags,并保存mask的图像。
执行填充算法的效果如图3.25所示。
图3.25
mask的保存图像如图3.26所示。
图3.26
多次调用填充算法,使用mask可以保证填充区域不会发生重叠。