![深度学习计算机视觉实战](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=1739000528-QRmUHMMSMe4bqS0y0EE3y6xDVKsPECo2-0-24a8c8f2c2c9c8a4651c92b2654424d7)
C++版本另一个重载的函数如下:
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_75_2.jpg?sign=1739000528-3CSr5NN4tK6EdFlBLfCL0BIAPhbQSOBN-0-1ca2ceb04c6fe4850baa9bf0c65a9985)
两个函数的差异是第二个函数多了一个参数InputOutputArray mask,其他的参数都是完全一样的。
Python版本对应的函数如下:
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_75_3.jpg?sign=1739000528-fvc09mpi4DKEpWHkR9QsSoS7LDoac1eU-0-1e299c1a6a13bc58d47cb862828ea78a)
floodFill函数对应的参数及其含义如表3.11所示。
表3.11
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_75_4.jpg?sign=1739000528-5toOKEGtXb3uyJTE9nWwIbBgrrg7dZIJ-0-030fd2dea4f22c47ef2b2106ee3abd27)
续表
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_76_1.jpg?sign=1739000528-2TXApzFIKwIVhGHl0kB8vOLvk1dwlxgi-0-7026e1a392fe4c2a6eaadc1d5b2dd4a9)
表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=1739000528-7fd2MLZjXcTeVgy93YLJ5DjMTJdS1Hkv-0-60b4e3352730b1ebeec8f7d7558925b2)
FloodFillFlags函数对应的参数及其含义如表3.12所示。
表3.12
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_76_3.jpg?sign=1739000528-3FrB9J0u5EW7bi5UU3U6iZdxtsGhRa5D-0-4e13b2f482f08231a9ce1cd219d87f95)
所有的标志位可以通过按位或“|”运算连接。例如,使用8连通域,并且只填充mask,填充值为255,设置这个标志位如下:
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_76_4.jpg?sign=1739000528-PCuUjxlhLPRYlWiN7ub5HN62h2rMOmQv-0-4bdbc5899e6f348c74f2810f72ac8cee)
下面通过案例来展示漫水填充的使用效果。这里使用一张优美的城市夜景作为案例的源图像,如图3.22所示。
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_77_1.jpg?sign=1739000528-V3UfG4gJ21p6CmlteCs1e6DNlzSX3eSM-0-666ed08acb6ef8463f8af0d2d7404801)
图3.22
应用漫水填充算法的代码如下:
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_77_2.jpg?sign=1739000528-bOTUJCWu0KXgFb5XUI16g6QWkRrbJDVL-0-1bc91ecac11e51292b7fc62d44ed7147)
在本次操作中,选择的注水点是坐标值为(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=1739000528-DdJdWOLAfjqZoF4J8TQoGPzfBbmmTifT-0-5a40a8f654398e8229bbb86a5fc9c2a9)
图3.23
可以通过mask控制执行填充算法的区域,mask填充为0的区域才会执行填充算法,接下来对图像的右边部分执行漫水填充,代码如下:
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_78_1.jpg?sign=1739000528-GITK6mNKCYmaoK9es4GLCysQwu8EPN5Y-0-399eb56757fb6725b8873dbbedfd7f07)
在创建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=1739000528-oq4yIfHM4AEQN4zxnshDu8gt06EIpGaZ-0-ca490ceff585a1cc6bfeb0e811358364)
图3.24
对比图3.23可以看到,只有图像的右边区域执行了填充算法。
接下来在执行填充算法前,添加标志flags,并保存mask的图像。
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_78_3.jpg?sign=1739000528-K4rItZJfKn814KjIlaWdyJyzVlO1u7EJ-0-fc558f92d08d94c862d47693bd83f236)
执行填充算法的效果如图3.25所示。
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_79_1.jpg?sign=1739000528-n6kw3lRoyb1o7oOAGvbPnrTGmcSwwyer-0-053e4ad8e0ad185d884b66c584e43e7d)
图3.25
mask的保存图像如图3.26所示。
![](https://epubservercos.yuewen.com/6C0CD6/21190708401165406/epubprivate/OEBPS/Images/41759_79_2.jpg?sign=1739000528-Qfo9nJwN8RqxkAUZ2QpodGYOMPFGfJ47-0-c0be4f1d5a3e38406d4dbd5797f871f2)
图3.26
多次调用填充算法,使用mask可以保证填充区域不会发生重叠。