【OpenCV 4开发详解】漫水填充法
本文首发于“小白学视觉”微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究!
经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。 |
漫水填充算法是根据像素灰度值之间的差值寻找相同区域实现分割。我们可以将图像的灰度值理解成像素点的高度,这样一张图像可以看成崎岖不平的地面或者山区,向地面上某一个低洼的地方倾倒一定量的水,水将会掩盖低于某个高度的区域。漫水填充法利用的就是这样的原理,其形式与注水相似,因此被称形象的称为“漫水”。
与向地面注水一致,漫水填充法也需要在图像选择一个注水像素,该像素被称为种子点,种子点按照一定规则不断向外扩散,从而形成具有相似特征的独立区域,进而实现图像分割。漫水填充分割法主要分为3以下三个步骤:
- Step1:选择种子点(x,y)(x,y)(x,y);
- Step2:以种子点为中心,判断4邻域或者8邻域的像素值与种子点像素值的差值,将差值小于阈值的像素点添加进区域内。
- Step3:将新加入的像素点作为新的种子点,反复执行Step2,直到没有新的像素点被添加进该区域。
OpenCV 4提供了floodFill函数用于实现漫水填充法分割图像,该函数有两种函数原型,代码清单8-16中给出其中一种函数原型。
代码清单8-16 floodFill()函数原型1
1. int cv::floodFill(InputOutputArray image,
2. InputOutputArray mask,
3. Point seedPoint,
4. Scalar newVal,
5. Rect * rect = 0,
6. Scalar loDiff = Scalar(),
7. Scalar upDiff = Scalar(),
8. int flags = 4
9. )
- image:输入输出图像,图像数据类型可以为CV_8U或者CV_32F的单通道或者三通道图像。
- mask:掩码矩阵,尺寸比如输入图像的宽和高各大2的单通道图像,用于标记漫水填充的区域。
- seedPoint:种子点。
- newVal:归入种子点区域内像素点的新像素值。
- rect:种子点漫水填充区域的最小矩形边界,默认值为0,表示不输出边界。
- loDiff:添加进种子点区域条件的下界差值,当邻域某像素点的像素值与种子点像素值的差值大于该值时,该像素点被添加进种子点所在的区域。
- upDiff:添加进种子点区域条件的上界差值,当种子点像素值与邻域某像素点的像素值的差值小于该值时,该像素点被添加进种子点所在的区域。
- flags:漫水填充方法的操作标志,其由三部分构成,分别表示邻域种类、掩码像素值和填充算法的规则,填充算法规则可选择的参数在表8-7给出。
表8-3 inpaint()函数修复图像算法可选择标志
标志参数 | 简记 | 含义 |
---|---|---|
FLOODFILL_FIXED_RANGE | 1<<16 | 如果设置该参数,则仅考虑当前像素值与初始种子点像素值之间的差值,否则考虑新种子点像素值与当前像素值之间的差异,即范围是否浮动的标志。 |
FLOODFILL_MASK_ONLY | 1<<17 | 如果设置,该函数不会更改原始图像,即忽略第四个参数newVal,只生成掩码矩阵。 |
该函数可以根据给定像素点的像素值,寻找邻域内与其像素值接近的区域。该函数的第一个参数既是输入图像又是输出图像,可以是CV_8U或者CV_32F的单通道或者三通道图像。第二个参数是漫水填充的掩码矩阵,非0像素点表示在原图像中被填充的区域。掩码矩阵的宽和高要比原图像的宽和高大2,并且需要在函数之前将该矩阵初始化。函数第三个参数是种子点,可以是图像范围内任意一点。函数第四个参数是被填充像素点的新像素值,该值会直接作用在原图中,对原图进行修改。第五个参数是填充像素的最小矩形区域。第六个和第七个参数是像素点被填充的阈值条件,分别表示范围的下界和上界。最后一个参数是填充方法的操作标志,该标志由三部分组成,第一部分表示邻域的种类,可以选择值为4(表示4-邻域)和8(表示8-邻域);第二部分表示掩码矩阵中表示被填充像素点的像素值;第三部分是填充规则的标志,其可选择的参数在表8-7给出,这三部分可以通过“|”符号连接,例如“4|(255<<8)| FLOODFILL_FIXED_RANGE”。
有时我们并不需要使用掩码矩阵,输入掩码矩阵是对内存资源的浪费,因此OpenCV 4提供了floodFill()函数第二种原型,用于不输出掩码矩阵,代码清单8-17中给出了这种函数原型。
代码清单8-17 floodFill()函数原型2
1. int cv::floodFill(InputOutputArray image,
2. Point seedPoint,
3. Scalar newVal,
4. Rect * rect = 0,
5. Scalar loDiff = Scalar(),
6. Scalar upDiff = Scalar(),
7. int flags = 4
8. )
函数所有参数的含义与代码清单8-16中的相同,这里不再赘述,不过需要注意的是函数最后一个参数在可选值的范围上有些变换,由于函数不输出掩码矩阵,因此FLOODFILL_MASK_ONLY标志不起任何作用,因此该种函数原型中没有任何意义,甚至可以缺省表示掩码矩阵中被填充像素点的新像素值的第二部分。
为了了解该函数的使用方法以及漫水填充分割的效果,在代码清单8-18中给出了利用floodFill()函数对图像进行分割的示例程序。程序中每一次循环都会随机生成一个像素点,并对这个像素点进行漫水填充,图8-10给出了填充结果和掩码矩阵,同时输出每个像素点的坐标和填充像素点的数目,输出结果如图8-11所示。
代码清单8-18 myFloodfill.cpp漫水填充分割图像
1. #include <opencv2\opencv.hpp>
2. #include <iostream>
3.
4. using namespace cv;
5. using namespace std;
6.
7. int main()
8. {9. system("color F0"); //将DOS界面调成白底黑字
10. Mat img = imread("lena.png");
11. if (!(img.data))
12. {13. cout << "读取图像错误,请确认图像文件是否正确" << endl;
14. return -1;
15. }
16.
17. RNG rng(10086);//随机数,用于随机生成像素
18.
19. //设置操作标志flags
20. int connectivity = 4; //连通邻域方式
21. int maskVal = 255; //掩码图像的数值
22. int flags = connectivity|(maskVal<<8)| FLOODFILL_FIXED_RANGE; //漫水填充操作方式标志
23.
24. //设置与选中像素点的差值
25. Scalar loDiff = Scalar(20, 20, 20);
26. Scalar upDiff = Scalar(20, 20, 20);
27.
28. //声明掩模矩阵变量
29. Mat mask = Mat::zeros(img.rows + 2, img.cols + 2, CV_8UC1);
30.
31. while (true)
32. {33. //随机产生图像中某一像素点
34. int py = rng.uniform(0,img.rows-1);
35. int px = rng.uniform(0, img.cols - 1);
36. Point point = Point(px, py);
37.
38. //彩色图像中填充的像素值
39. Scalar newVal = Scalar(rng.uniform(0, 255), rng.uniform(0, 255),
40. rng.uniform(0, 255));
41.
42. //漫水填充函数
43. int area = floodFill(img, mask, point, newVal, &Rect(),loDiff,upDiff,flags);
44.
45. //输出像素点和填充的像素数目
46. cout << "像素点x:" << point.x << " y:" << point.y
47. << " 填充像数数目:" << area << endl;
48.
49. //输出填充的图像结果
50. imshow("填充的彩色图像", img);
51. imshow("掩模图像", mask);
52.
53. //判断是否结束程序
54. int c = waitKey(0);
55. if ((c&255)==27)
56. {57. break;
58. }
59. }
60. return 0;
61. }
图8-10 myFloodfill.cpp程序填充结果
OpenCV 4开发详解 |
往期推荐 |
---|
【OpenCV 4开发详解】直方图应用 |
【OpenCV 4开发详解】图像模板匹配 |
【OpenCV 4开发详解】图像卷积 |
【OpenCV 4开发详解】图像噪声的种类与生成 |
【OpenCV 4开发详解】均值滤波 |
【OpenCV 4开发详解】方框滤波 |
【OpenCV 4开发详解】高斯滤波 |
【OpenCV 4开发详解】可分离滤波 |
【OpenCV 4开发详解】中值滤波 |
【OpenCV 4开发详解】边缘检测原理 |
【OpenCV 4开发详解】Scharr算子 |
【OpenCV 4开发详解】Laplacian算子 |
【OpenCV 4开发详解】Canny算法 |
【OpenCV 4开发详解】图像距离变换 |
【OpenCV 4开发详解】图像连通域分析 |
【OpenCV 4开发详解】图像腐蚀 |
【OpenCV 4开发详解】图像膨胀 |
【OpenCV 4开发详解】形态学应用 |
【OpenCV 4开发详解】检测直线 |
【OpenCV 4开发详解】直线拟合 |
【OpenCV 4开发详解】直线检测 |
【OpenCV 4开发详解】轮廓发现与绘制 |
【OpenCV 4开发详解】轮廓面积与长度 |
【OpenCV 4开发详解】图像矩的计算与应用 |
【OpenCV 4开发详解】点集拟合 |
【OpenCV 4开发详解】QR二维码检测 |
经过几个月的努力,市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》将春节后由人民邮电出版社发行。如果小伙伴觉得内容有帮助,希望到时候多多支持! |
关注小白的小伙伴可以提前看到书中的内容,我们创建了学习交流群,欢迎各位小伙伴添加小白微信加入交流群,添加小白时请备注“学习OpenCV 4”。 |
【OpenCV 4开发详解】漫水填充法相关推荐
- 【OpenCV 4开发详解】分割图像——分水岭法
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】深度神经网络应用实例
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】图像修复
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】分割图像——Mean-Shift分割算法
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】分割图像——Grabcut图像分割
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】形态学应用
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】图像膨胀
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】图像腐蚀
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】图像连通域分析
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
最新文章
- highcharts图表组件常见问题:highcharts图表组件错误集合分析大放送
- ThinkPHP多应用/多模块配置
- Linux 升级 Python 至 3.x
- contentwindow无法搜索对象_面试官:讲一下Jvm中如何判断对象的生死?
- linux下启动solr命令,如何自动启动Solr?
- -bash: id: command not found -bash: tty: command not found
- 电机的入门之路系列3--直流电机的工作原理
- Dom4j SAXReader Constructors
- 如何突破网吧禁止下载的限制~?
- python有道-Python爬去有道翻译
- 开源多云技术平台——Choerodon猪齿鱼发布0.23版本
- 计算机的时钟设置错误,谷歌浏览器用不了显示电脑时钟错误解决方法
- 莫斯科的年轻人(一)
- 每日一狗 · 比利牛斯山犬
- 使用电脑时经常遇到问题?来试试这四款小众的实用软件吧
- 历届上海电影节获奖名单
- 计算机网络-基本概念
- frustum pointnets训练代码学习笔记——kitti_object.py
- c++里面的protect和public、private有什么区别?
- 使用Java实现矩形 平行四边形 等腰三角形 菱形 倒三角
热门文章
- AI一分钟 | 华米发布全球首款可穿戴AI芯片;亚马逊年底上线至少8款Alexa设备
- 开源用于寻找系外行星的代码
- 从AlexNet到DenseNet,再到SENet,一文看懂图像分类领域的突破性进展
- Redis 实现限流的三种方式
- IDEA 这样配置注释模板,让你高出一个逼格
- 用了这么久配置中心,还不知道长轮询是什么?
- RabbitMQ 七种队列模式应用场景案例分析(通俗易懂)
- JDK1.8源码分析:线程安全的CopyOnWriteArrayList与CopyOnWriteArraySet
- 为什么SpringBoot的 jar 可以直接运行?
- Spring MVC 到 Spring BOOT 的简化之路