![深度学习计算机视觉实战](https://wfqqreader-1252317822.image.myqcloud.com/cover/183/40795183/b_40795183.jpg)
3.4 案例9:使用漫水填充
漫水填充算法是填充算法中最常见的一种,就是将图像中与注水点连通的区域填充为指定的颜色,在图像分割中有重要的作用。该算法的实现过程分为以下三个步骤:
(1)选择一个注水点,这个点就是用户想要将其填充为指定颜色的点。
(2)以这个注水点为中心,在它的4邻域或8邻域中寻找满足条件的像素点,条件是目标像素点的像素值与该点像素值的差值在一定的范围内,该范围就是指定的下限和上限之间。
(3)将邻域中符合条件的像素点作为新的注水点,反复操作步骤(2),直到没有新的像素点可以被指定为注水点。
OpenCV提供了漫水填充操作的函数floodFill()。
C++版本对应的函数如下:
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_75_1.jpg?sign=1739268318-uXeYJixsxtgylIiFsmBASkneHYiH47xo-0-0a81fcc07f1895db8430f014265f7490)
C++版本另一个重载的函数如下:
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_75_2.jpg?sign=1739268318-Eo8FX9MIzqpPcbRHY2KIux5hG8F2yYJw-0-7b6422fe482faed9affa2ff76c2d72a4)
两个函数的差异是第二个函数多了一个参数InputOutputArray mask,其他的参数都是完全一样的。
Python版本对应的函数如下:
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_75_3.jpg?sign=1739268318-aikkrPZEMCF3ir9Ufl56NeDbEsVpFn2p-0-653fc0f7bbdf8ef8c3a6c1d86818b817)
floodFill函数对应的参数及其含义如表3.11所示。
表3.11
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_75_4.jpg?sign=1739268318-3orIYbiK59oiZBMrtNoguFgQIDyOrena-0-183febda69c11c623a58e49adc6814f8)
续表
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_76_1.jpg?sign=1739268318-6I5zHcenopf8xmYZ0jvUbztNkRJNyEq7-0-795d6a092c54799d4c95bf30f1abcfb0)
表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的两个枚举值控制操作。
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_76_2.jpg?sign=1739268318-Koa4584YUgvpx6z3qDnaEIw7hufDWgMs-0-7ae4369fdb8a652852105fa495891225)
FloodFillFlags函数对应的参数及其含义如表3.12所示。
表3.12
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_76_3.jpg?sign=1739268318-Rf7OIcA9Q7avQLIsrGQg2cDPmxWnyBpA-0-f656764cad004379a4b3f9dfe095895a)
所有的标志位可以通过按位或“|”运算连接。例如,使用8连通域,并且只填充mask,填充值为255,设置这个标志位如下:
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_76_4.jpg?sign=1739268318-cEUNjhHiO19BBZqlhDefaVOXUtnFklhp-0-afeecb842dc4ab3aaca0c50e467ab180)
下面通过案例来展示漫水填充的使用效果。这里使用一张优美的城市夜景作为案例的源图像,如图3.22所示。
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_77_1.jpg?sign=1739268318-0rgH3K9XnJ2XMh3UegNebTJ6egUAABT8-0-167f9fb536e4134b871e8fbd16bf9675)
图3.22
应用漫水填充算法的代码如下:
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_77_2.jpg?sign=1739268318-d5T4JW6C8eUoAP7ZMIOW1A9SZeejwQJx-0-4b0f23980c3661ed04ddb536e4346bd8)
在本次操作中,选择的注水点是坐标值为(1100,800)的点,被操作的图像copy_img在执行填充算法后被填充为黑色,像素的差值的下限为(30,30,30),上限为(40,40,40)。填充后的图像结果如图3.23所示。
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_77_3.jpg?sign=1739268318-KdGiBXfMj2p1vohi4msuRuo0p8LGnv7z-0-7319b8f997c3909a0f11fa97bb898bc7)
图3.23
可以通过mask控制执行填充算法的区域,mask填充为0的区域才会执行填充算法,接下来对图像的右边部分执行漫水填充,代码如下:
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_78_1.jpg?sign=1739268318-kYXQzgplWPAXJlx3h4ktsvl7ky4gTNX5-0-94e18be351ae109c2148d5a9851dc691)
在创建mask1时全部赋值为1,此时整个输入图像区域均会执行填充算法。本案例源图像的尺寸为2000×1125,执行mask1[:,1000:]=0就是将图片从位置1000到最右边均赋值为0,因而图像左边区域不执行填充算法,只有右边区域执行填充算法,效果如图3.24所示。
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_78_2.jpg?sign=1739268318-Q94vdxbFdxIJyKJvbYRuxEuAn6SloxEz-0-9b9665e72a45610668832bcc7e014f36)
图3.24
对比图3.23可以看到,只有图像的右边区域执行了填充算法。
接下来在执行填充算法前,添加标志flags,并保存mask的图像。
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_78_3.jpg?sign=1739268318-rGKVJSBvUEULuBbzNC8esdQXHR5p9Thr-0-2abd608fd888f3b234e6fc1302dba0b2)
执行填充算法的效果如图3.25所示。
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_79_1.jpg?sign=1739268318-LdK0qqdr08FFLCo21TEsFuQm9n5zc4DL-0-ab58c4fe8d5c1f43ad42ebe76287e156)
图3.25
mask的保存图像如图3.26所示。
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_79_2.jpg?sign=1739268318-kXOw1S7TIjEo5IRwAQ30VMtNCpz8WzSS-0-077ff2361233a5b8e670223adb7dac76)
图3.26
多次调用填充算法,使用mask可以保证填充区域不会发生重叠。