https://blog.csdn.net/weixin_42296411/article/details/80966724

函数原型

参数:

image 【输入/输出】 1或者3通道、 8bit或者浮点图像。仅当参数flags的FLOODFILL_MASK_ONLY标志位被设置时image不会被修改,否则会被修改。

mask 【输入/输出】 操作掩码,必须为单通道、8bit,且比image宽2个像素、高2个像素。使用前必须先初始化。Flood-filling无法跨越mask中的非0像素。例如,一个边缘检测的结果可以作为mask来阻止边缘填充。在输出中,mask中与image中填充像素对应的像素点被设置为1,或者flags标志位中设置的值(详见flags标志位的解释)。此外,该函数还用1填充了mask的边缘来简化内部处理。因此,可以在多个调用中使用同一mask,以确保填充区域不会重叠。

seedPoint 起始像素点

newVal   重绘像素区域的新的填充值(颜色)

rect      可选输出参数,返回重绘区域的最小绑定矩形。

loDiff     当前选定像素与其连通区中相邻像素中的一个像素,或者与加入该连通区的一个seedPoint像素,二者之间的最大下行差异值。

upDiff    当前选定像素与其连通区中相邻像素中的一个像素,或者与加入该连通区的一个seedPoint像素,二者之间的最大上行差异值。

flags     flags标志位是一个32bit的int类型数据,其由3部分组成: 0-7bit表示邻接性(4邻接、8邻接);8-15bit表示mask的填充颜色;16-31bit表示填充模式(详见填充模式解释)

flood fill填充模式:

//! floodfill algorithm flags

enum FloodFillFlags {

/** If set, the difference between the current pixel andseed pixel is considered. Otherwise,

the difference between neighbor pixels is considered (that is, the rangeis floating). */

FLOODFILL_FIXED_RANGE = 1 << 16,

/** If set, the function does not change the image ( newValis ignored), and only fills the

mask with the value specified in bits 8-16 of flags as described above.This option only make

sense in function variants that have the mask parameter. */

FLOODFILL_MASK_ONLY   = 1 <<17

};

FLOODFILL_FIXED_RANGE:如果设置了该值,则考虑当前像素与seed像素之间的差异,否则考虑相邻像素之间的差异(即浮动区间)。

FLOODFILL_MASK_ONLY:如果设置了该值,floodFill函数不会修改image的内容(newVal被忽略),只使用flags标志中bit8-15的值填充mask。该选项仅在含mask参数的floodFill函数中有效。

函数作用:

用给定的颜色填充一个连通区域。

下面我们通过Code来演示floodFill函数的用法及效果:

先创建一个20*10像素的灰度图像,为了便于观察,我们以60个灰度为一个等级填充图片。

Code-1:

  1. import cv2
  2. import numpy as np
  3. img = np.zeros((20,10), dtype=np.uint8)
  4. i = 0
  5. for v in img:
  6. v[:] = i//5 * 60
  7. i += 1
  8. cv2.imshow('img', img)
  9. cv2.waitKey(0)
  10. cv2.destroyAllWindows()

得到的图片输出(为方便观察,使用画图软件打开,下同):

该图片被分为4个横条块,其灰度值自顶向下依次为:0、60、120、180。

接下来,我们选定seed=(7,7), 该点落在这里(下图第二个横条小白点处):

我们选定该点作为seedPoint,对img图片进行floodFill。

Code-2:

  1. #encoding=utf-8
  2. import cv2
  3. import numpy as np
  4. img = np.zeros((20,10), dtype=np.uint8)
  5. i = 0
  6. for v in img:
  7. v[:] = i//5 * 60
  8. i += 1
  9. cv2.imwrite('img_init.png', img)
  10. seed = (7, 7)
  11. #构建mask,根据mask参数的介绍,其size必须为宽img+2,高img+2
  12. mask = np.zeros((img.shape[0]+2, img.shape[1] +2), dtype=np.uint8)
  13. newVal = (127) #img fill的填充值
  14. mask_fill = 252 #mask的填充值
  15. #floodFill充值标志
  16. flags = 4|(mask_fill<<8)|cv2.FLOODFILL_FIXED_RANGE
  17. #连通区范围设定
  18. loDiff, upDiff = 20,20
  19. #执行floodFill操作
  20. ret, image, mask, rect = cv2.floodFill(img, mask, seed, newVal,(loDiff), (upDiff), flags)
  21. cv2.imwrite('img.png', img)
  22. cv2.imwrite('img_mask.png', mask)

floodFill前、后的img图像(左前右后):

对比发现,img图像的第二行颜色变了,check一下第二行的颜色值,发现变为了127,这与Code-2中

newVal =(127)#img fill的填充值

是一致的:

再check一下得到的mask图像:

其像素值为:

我们观察mask的像素组成会发现,执行floodFill后得到的mask值,其被填充部分的值来自于:

mask_fill =252 #mask的填充值

并且,最外围边缘一周的像素点,全部被填充为1,这与mask参数的描述完全一致。

接下来,我们调整一下loDiff的值为70,我们看看会有什么不一样:

loDiff, upDiff =70,20

得到的img图像为:

与原始img图片对比:

观察floodFill后的img像素值:

我们发现img图像第一、二行的值均被置为127了,这是因为当loDiff值为70时,seed=(7,7)所在点的值为60,而60-loDiff=-10,60+upDiff=80,而img图片第一、二行的像素值分别为0和60,均值[-10,80]这个区间内,故img图片第一、二行均被填充。

以上都是基于FLOODFILL_FIXED_RANGE这种填充方式的,下面我们对比一下使用FLOODFILL_MASK_ONLY方式来填充会有什么不一样。其他code保存不变,我们只需将

flags =4|(mask_fill<<8)|cv2.FLOODFILL_FIXED_RANGE

改为:

flags =4|(mask_fill<<8)|cv2.FLOODFILL_MASK_ONLY

运行程序后,发现img图片第一、第二行的值均未发生变化:

但mask图片第一、第二行的值与前面使用FLOODFILL_FIXED_RANGE时是一样的:

故此,可以验证前面对FLOODFILL_MASK_ONLY的解释,只影响mask的输出,对image无影响。

最后,对flags的0-7bit邻接性进行分析。

相邻像素

1)     4领域

对位于坐标(x,y)的像素p有4个水平和垂直的相邻像素,它们的坐标是:

(x+1,y), (x-1,y),(x,y+1),(x,y-1)

这组像素称为p的4邻域,用N4(p)表示:

对角相邻像素

p的四个对角像素的坐标为:

(x+1,y+1), (x+1,y-1),(x-1,y+1),(x-1,y-1)

ND(p)表示:

8领域

N4(p)和ND(p)组成像素p的8个相邻像素,称为p的8邻域,用N8(p)表示:

邻接性

4邻接-如果q在集合N4(p)中,则pq是4邻接。

8邻接-如果q在集合N8(p)中,则pq是8邻接。

最后,通过代码来演示一下:

Code-3-1:

  1. #encoding=utf-8
  2. #创建一个8x8的图片
  3. import cv2
  4. import numpy as np
  5. size = 8
  6. img = np.zeros((size,size), dtype=np.uint8)
  7. img[:] = 0
  8. img[4,4] = 1
  9. img[3,4] = 1
  10. img[4,3] = 1
  11. img[4,5] = 1
  12. img[5,4] = 1
  13. img[2,4] = 1
  14. img[1,5] = 1
  15. img[1,3] = 1
  16. img[2,2] = 1
  17. img[3,1] = 1
  18. img[4,0] = 1
  19. img[5,1] = 1
  20. img[6,2] = 1
  21. img[7,3] = 1
  22. print(img)

创建一个以p(4,4)为中心像素的8x8图像:

下面以p(4,4)作为seed,对该图像进行floodFill操作,对比4邻接和8邻接的差异。

Code-3-2:

  1. #encoding=utf-8
  2. #创建一个8x8的图片
  3. import cv2
  4. import numpy as np
  5. size = 8
  6. img = np.zeros((size,size), dtype=np.uint8)
  7. img[:] = 0
  8. seed_x = 4
  9. seed_y = 4
  10. img[seed_x, seed_y] = 1
  11. img[4,4] = 1
  12. img[3,4] = 1
  13. img[4,3] = 1
  14. img[4,5] = 1
  15. img[5,4] = 1
  16. img[2,4] = 1
  17. img[1,5] = 1
  18. img[1,3] = 1
  19. img[2,2] = 1
  20. img[3,1] = 1
  21. img[4,0] = 1
  22. img[5,1] = 1
  23. img[6,2] = 1
  24. img[7,3] = 1
  25. seed = (seed_x, seed_y)
  26. mask= np.zeros((size+2,size+2), dtype=np.uint8)
  27. img1 = img.copy()
  28. img2 = img.copy()
  29. mask1 = mask.copy()
  30. mask2 = mask.copy()
  31. ret, img1,mask1, rect=cv2.floodFill(img1, mask1, seed,(8), (0),(0), flags=4|(3<<2)|cv2.FLOODFILL_FIXED_RANGE)
  32. ret, img2,mask2, rect=cv2.floodFill(img2, mask2, seed,(8), (0),(0), flags=8|(3<<2)|cv2.FLOODFILL_FIXED_RANGE)
  33. print(img)
  34. print(img1)
  35. print(img2)

img1为4邻接填充:

img2为8邻接填充:

  •                     <li class="tool-item tool-active is-like "><a href="javascript:;"><svg class="icon" aria-hidden="true"><use xlink:href="#csdnc-thumbsup"></use></svg><span class="name">点赞</span><span class="count">4</span></a></li><li class="tool-item tool-active is-collection "><a href="javascript:;" data-report-click="{&quot;mod&quot;:&quot;popu_824&quot;}"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-csdnc-Collection-G"></use></svg><span class="name">收藏</span></a></li><li class="tool-item tool-active is-share"><a href="javascript:;"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-csdnc-fenxiang"></use></svg>分享</a></li><!--打赏开始--><!--打赏结束--><li class="tool-item tool-more"><a><svg t="1575545411852" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5717" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M179.176 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5718"></path><path d="M509.684 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5719"></path><path d="M846.175 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5720"></path></svg></a><ul class="more-box"><li class="item"><a class="article-report">文章举报</a></li></ul></li></ul></div></div><div class="person-messagebox"><div class="left-message"><a href="https://blog.csdn.net/weixin_42296411"><img src="https://profile.csdnimg.cn/0/4/8/3_weixin_42296411" class="avatar_pic" username="weixin_42296411"><img src="https://g.csdnimg.cn/static/user-reg-year/2x/2.png" class="user-years"></a></div><div class="middle-message"><div class="title"><span class="tit"><a href="https://blog.csdn.net/weixin_42296411" data-report-click="{&quot;mod&quot;:&quot;popu_379&quot;}" target="_blank">weixin_42296411</a></span></div><div class="text"><span>发布了2 篇原创文章</span> · <span>获赞 10</span> · <span>访问量 2万+</span></div></div><div class="right-message"><a href="https://im.csdn.net/im/main.html?userName=weixin_42296411" target="_blank" class="btn btn-sm btn-red-hollow bt-button personal-letter">私信</a><a class="btn btn-sm  bt-button personal-watch" data-report-click="{&quot;mod&quot;:&quot;popu_379&quot;}">关注</a></div></div></div>
    

floodFill详解相关推荐

  1. FloodFill算法详解及应用

    FloodFill算法详解及应用 啥是 FloodFill 算法呢, 最直接的一个应用就是「颜色填充」,就是 Windows 绘画本中那个小油漆桶的标志,可以把一块被圈起来的区域全部染色. 这种算法思 ...

  2. 【OpenCV 4开发详解】漫水填充法

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  3. Windows API函数大全---附:windows运行命令详解

    1. API之网络函数             WNetAddConnection 创建同一个网络资源的永久性连接             WNetAddConnection2 创建同一个网络资源的连 ...

  4. [opencv完整项目详解] 传统图像算法解决路标的检测和识别(改进升级版)

    之前路标匹配[opencv完整项目详解] 传统图像算法解决路标的检测和识别 的一个改进版. 之前路标匹配存在的一个问题: 所有路标与模板的相似度都处于较高状态(基本都在50%以上),其主要原因就是虽然 ...

  5. [opencv完整项目详解] 传统图像算法解决路标的检测和识别

    前言: 这是数字图像课程的大作业,老师要求不可以采用深度学习的方法检测和识别特定的路标,只能采用传统的图像算法提取特征从而检测出特定的车牌. 参考文章: https://blog.csdn.net/m ...

  6. 详解python中GPU版本的opencv常用方法介绍

    更多编程教程请到:菜鸟教程 https://www.piaodoo.com/ 友情链接:好看站 http://www.nrso.net/ 高州阳光论坛https://www.hnthzk.com/ 引 ...

  7. 从命令行到IDE,版本管理工具Git详解(远程仓库创建+命令行讲解+IDEA集成使用)

    首先,Git已经并不只是GitHub,而是所有基于Git的平台,只要在你的电脑上面下载了Git,你就可以通过Git去管理"基于Git的平台"上的代码,常用的平台有GitHub.Gi ...

  8. JVM年轻代,老年代,永久代详解​​​​​​​

    秉承不重复造轮子的原则,查看印象笔记分享连接↓↓↓↓ 传送门:JVM年轻代,老年代,永久代详解 速读摘要 最近被问到了这个问题,解释的不是很清晰,有一些概念略微模糊,在此进行整理和记录,分享给大家.在 ...

  9. docker常用命令详解

    docker常用命令详解 本文只记录docker命令在大部分情境下的使用,如果想了解每一个选项的细节,请参考官方文档,这里只作为自己以后的备忘记录下来. 根据自己的理解,总的来说分为以下几种: Doc ...

最新文章

  1. 读《程序是怎样跑起来的》第5章
  2. 一起学nRF51xx 12 -  flash
  3. 集群监控系统的设计方案
  4. Python手册 3.7
  5. centos配置单网卡双IP
  6. pycharm安装带激活码2018
  7. iOS利用代理实现界面跳转
  8. jQuery源码学习(一)
  9. Astar寻路教程!
  10. 等差数列及等比数列求和公式
  11. 学生档案信息管理系统(Java实现)
  12. webpack ——css兼容性处理
  13. 在电脑上微信无法语音聊天,微信听不到语音声音
  14. Guava源码解析五:Splitter源码解析
  15. android webview 手机兼容问题
  16. 【luogu CF1153F】Serval and Bonus Problem(期望)(DP)
  17. 怎么把解压的文件在HTML打开,解决电脑rar压缩包文件怎么打开?教你正确打开方式...
  18. 台式电脑如何修复计算机,大神告诉你电脑不断重启如何修复
  19. Java实现统计字符次数(按大写、小写、数字来统计)
  20. 找不到 Microsoft Excel Driver ODBC 驱动程序的安装例程 解决方案

热门文章

  1. Redis使用的21条军规(规范)
  2. zip压缩包密码解密
  3. 量化交易入门阶段——欧奈尔的CANSLIM模型(A 年度净利润同比增长率)
  4. 【软考二】程序设计语言(做题)
  5. 查询出学生表中年龄和分数相同的所有同学的名字
  6. linux下rsync命令,Linux 命令之rsync命令详解
  7. 搭建WebRTC服务器
  8. 条件随机场(2)——概率计算
  9. StringBuffer的使用
  10. android数字转汉字,【原创】最精简的中文数字和阿拉伯数字互相转换函数