OpenCV学习笔记(九): 漫水填充:floodFill()

OpenCV学习笔记(九): 漫水填充:floodFill()

定义:
漫水填充法是一种用特定的颜色填充联通区域(自动选中了和种子点相连的区域,接着将该区域替换成指定的颜色)通过设置可连通像素的上下限以及连通方式来达到不同的填充效果的方法。
使用:
1)经常被用来标记或分离图像的一部分,以便对其进行进一步处理或分析。
2)从输入图像获取掩码区域(掩码会加速处理过程,或只处理掩码指定的像素点,操作的结果总是某个连续的区域)
算子:

int floodFill(
InputOutputArray image, // 1.输入/输出图像
InputOutputArray mask, 	// 2.这是第二个版本的floodFill独享的参数,表示操作掩模(它应该为单通道、8位、长和宽上都比输入图像 image 大两个像素点的图像)
Point seedPoint,		// 3.漫水填充算法的起始点
Scalar newVal, 			// 4.在重绘区域像素点被染色的新值
Rect* rect=0, 			// 5.一个可选的参数,将要重绘区域的最小边界矩形区域
Scalar loDiff=Scalar(), // 6.loDiff 负差最大值(当前像素与领域像素或种子像素颜色或亮度的)
Scalar upDiff=Scalar(), // 7.upDiff 正差最大值(当前像素与领域像素或种子像素颜色或亮度的)
int flags=4 			// 8.操作标志符
)

// PS:
1、漫水填充不会填充掩膜mask的非零像素区域。例如,一个边缘检测算子的输出可以用来作为掩膜,以防止填充到边缘。同样的,也可以在多次的函数调用中使用同一个掩膜,以保证填充的区域不会重叠。另外需要注意的是,
掩膜mask会比需填充的图像大,所以 mask 中与输入图像(x,y)像素点相对应的点的坐标为(x+1,y+1)。
2、
1)低八位(第0~7位)用于控制算法的连通性,可取4 (4为缺省值) 或者 8。

如果设为4,表示填充算法只考虑当前像素水平方向和垂直方向的相邻点;
如果设为 8,除上述相邻点外,还会包含对角线方向的相邻点。

2)高八位部分(16~23位)可以为0 或者如下两种选项标识符的组合:

FLOODFILL_FIXED_RANGE - 如果设置为这个标识符的话,就会考虑当前像素与种子像素之间的差,
否则就考虑当前像素与其相邻像素的差。也就是说,这个范围是浮动的。
FLOODFILL_MASK_ONLY - 如果设置为这个标识符的话,函数不会去填充改变原始图像 (也就是忽略第三个参数newVal), 
而是去填充掩模图像(mask)。

3)中间八位部分,上面关于高八位FLOODFILL_MASK_ONLY标识符中已经说的很明显,需要输入符合要求的掩码。Floodfill的flags参数的中间八位的值就是用于指定填充掩码图像的值的。但如果flags中间八位的值为0,则掩码会用1来填充。

//如果想用8邻域填充,并填充固定像素值范围,填充掩码而不是填充源图像,以及设填充值为38
flags=8 | FLOODFILL_MASK_ONLY | FLOODFILL_FIXED_RANGE |38<<8

示例代码:

#include <opencv2/opencv.hpp>using namespace cv;
using namespace std;Mat g_srcImage, g_dstImage, g_grayImage, g_maskImage;        //定义原始图、目标图、灰度图、掩模图
int g_nFillMode = 1;                                         //漫水填充的模式
int g_nLowDifference = 20, g_nUpDifference = 20;             //负差最大值、正差最大值
int g_nConnectivity = 4;                                     //表示floodFill函数标识符低八位的连通值
bool g_bIsColor = true;                                      //是否为彩色图的标识
bool g_bUseMask = false;                                     //是否显示掩膜窗口的标识
int g_nNewMaskVal = 255;                                     //新的重新绘制的像素值int main()
{//显示帮助文字ShowHelpText();// 1、载入原图g_srcImage = imread("F:/C++/2. OPENCV 3.1.0/TEST/2.jpg", 1);if( !g_srcImage.data ){printf("读取图片image0错误~! \n");return false;}// 2、拷贝源图到目标图g_srcImage.copyTo(g_dstImage);// 3、转换三通道的image0到灰度图cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);// 4、利用image0的尺寸来初始化掩膜maskg_maskImage.create(g_srcImage.rows+2, g_srcImage.cols+2, CV_8UC1);// 5、创建TrackbarnamedWindow( "效果图",WINDOW_AUTOSIZE );createTrackbar( "负差最大值", "效果图", &g_nLowDifference, 255, 0 );    // 无滑动条事件,只改变滑动条值(0~255)createTrackbar( "正差最大值" ,"效果图", &g_nUpDifference, 255, 0 );      // 无滑动条事件,只改变滑动条值(0~255)// 6、鼠标回调函数(鼠标点击便触发)// 将mask所有元素设置为0(背景设为黑色)g_maskImage = Scalar::all(0);     setMouseCallback( "效果图", onMouse, 0 );// 7、循环轮询按键while(1){//先显示效果图imshow("效果图", g_bIsColor ? g_dstImage : g_grayImage);//获取键盘按键int c = waitKey(0);//判断ESC是否按下,若按下便退出if( (c & 255) == 27 ){cout << "程序退出...........\n";break;}//根据按键的不同,进行各种操作switch( (char)c ){//如果键盘“1”被按下,效果图在在灰度图,彩色图之间互换case '1':if( g_bIsColor )//若原来为彩色,转为灰度图,并且将掩膜mask所有元素设置为0{cout << "键盘“1”被按下,切换彩色/灰度模式,当前操作为将【彩色模式】切换为【灰度模式】\n";cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);g_maskImage = Scalar::all(0);           //将mask所有元素设置为0g_bIsColor = false;                         //将标识符置为false,表示当前图像不为彩色,而是灰度}else//若原来为灰度图,便将原来的彩图image0再次拷贝给image,并且将掩膜mask所有元素设置为0{cout << "键盘“1”被按下,切换彩色/灰度模式,当前操作为将【彩色模式】切换为【灰度模式】\n";g_srcImage.copyTo(g_dstImage);g_maskImage = Scalar::all(0);g_bIsColor = true;                  //将标识符置为true,表示当前图像模式为彩色}break;//如果键盘按键“2”被按下,显示/隐藏掩膜窗口case '2':if( g_bUseMask ){destroyWindow( "mask" );g_bUseMask = false;}else{namedWindow( "mask", 0 );//g_maskImage = Scalar::all(0); // 清空置零imshow("mask", g_maskImage);g_bUseMask = true;}break;//如果键盘按键“3”被按下,恢复原始图像case '3':cout << "按键“3”被按下,恢复原始图像\n";g_srcImage.copyTo(g_dstImage);cvtColor(g_dstImage, g_grayImage, COLOR_BGR2GRAY);g_maskImage = Scalar::all(0);break;// 改变”漫水填充“操作标识:// 1、如果键盘按键“4”被按下,使用空范围的漫水填充case '4':cout << "按键“4”被按下,使用空范围的漫水填充\n";g_nFillMode = 0;break;// 2、如果键盘按键“5”被按下,使用渐变、固定范围的漫水填充case '5':cout << "按键“5”被按下,使用渐变、固定范围的漫水填充\n";g_nFillMode = 1;break;// 3、如果键盘按键“6”被按下,使用渐变、浮动范围的漫水填充case '6':cout << "按键“6”被按下,使用渐变、浮动范围的漫水填充\n";g_nFillMode = 2;break;// 4、如果键盘按键“7”被按下,操作标志符的低八位使用4位的连接模式case '7':cout << "按键“7”被按下,操作标志符的低八位使用4位的连接模式\n";g_nConnectivity = 4;break;// 5、如果键盘按键“8”被按下,操作标志符的低八位使用8位的连接模式case '8':cout << "按键“8”被按下,操作标志符的低八位使用8位的连接模式\n";g_nConnectivity = 8;break;}}
}

输出一些帮助信息

static void ShowHelpText()
{printf("\n\n\t漫水填充示例程序~");printf("\n\n\t根据鼠标选取的点搜索图像中与之颜色相近的点,并用不同颜色标注。");printf("\n\n\t按键操作说明: \n\n""\t\t鼠标点击图中区域- 进行漫水填充操作\n""\t\t键盘按键【ESC】- 退出程序\n""\t\t键盘按键【1】-  切换彩色图/灰度图模式\n""\t\t键盘按键【2】- 显示/隐藏掩膜窗口\n""\t\t键盘按键【3】- 恢复原始图像\n""\t\t键盘按键【4】- 使用空范围的漫水填充\n""\t\t键盘按键【5】- 使用渐变、固定范围的漫水填充\n""\t\t键盘按键【6】- 使用渐变、浮动范围的漫水填充\n""\t\t键盘按键【7】- 操作标志符的低八位使用4位的连接模式\n""\t\t键盘按键【8】- 操作标志符的低八位使用8位的连接模式\n\n");
}

鼠标消息onMouse回调

static void onMouse(int event, int x, int y, int, void*)
{if (event != EVENT_LBUTTONDOWN)return;// 1、调用floodFill函数之前的参数准备部分Point seed = Point(x, y);   // 鼠标点击获取起始点位置int LowDifference = g_nFillMode == 0 ? 0 : g_nLowDifference;    //空范围的漫水填充,此值设为0,否则设为全局的g_nLowDifferenceint UpDifference = g_nFillMode == 0 ? 0 : g_nUpDifference;      //空范围的漫水填充,此值设为0,否则设为全局的g_nUpDifference// 1.1、floodFill()函数第八个参数值:flags=低八位+中八位+高八位int flags = g_nConnectivity + (g_nNewMaskVal << 8) + (g_nFillMode == 1 ? FLOODFILL_FIXED_RANGE : 0); // FLOODFILL_FIXED_RANGE// 1.2、随机生成bgr值int b = (unsigned)theRNG() & 255;//随机返回一个0~255之间的值int g = (unsigned)theRNG() & 255;//随机返回一个0~255之间的值int r = (unsigned)theRNG() & 255;//随机返回一个0~255之间的值Rect ccomp;//定义重绘区域的最小边界矩形区域// 1.3、在重绘区域像素的新值,若是彩色图模式,取Scalar(b, g, r);若是灰度图模式,取Scalar(r*0.299 + g*0.587 + b*0.114)Scalar newVal = g_bIsColor ? Scalar(b, g, r) : Scalar(r*0.299 + g*0.587 + b*0.114);Mat dst = g_bIsColor ? g_dstImage : g_grayImage;//目标图的赋值// 2、正式调用floodFill函数threshold(g_maskImage, g_maskImage, 1, 128, THRESH_BINARY);// 带掩码输出的 floodFill()int area = floodFill(dst, g_maskImage, seed, newVal, &ccomp, Scalar(LowDifference, LowDifference, LowDifference),Scalar(UpDifference, UpDifference, UpDifference), flags);// 3、关闭或显示掩码窗口if (g_bUseMask){imshow("mask", g_maskImage);}
//    else
//    {
//        // 不带掩码输出的 floodFill()
//        area = floodFill(dst, seed, newVal, &ccomp, Scalar(LowDifference, LowDifference, LowDifference),
//            Scalar(UpDifference, UpDifference, UpDifference), flags);
//    }imshow("效果图", dst);cout << area << " 个像素被重绘\n";
}

结果:
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/491173.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

68页PPT,读懂中、美、德三国智能制造战略!

来源&#xff1a;清华大学深圳研究生院导 读这份来自清华大学深圳研究生院物流与交通学部的研究和报告&#xff0c;分析了工业4.0趋势下德、中、美竞争与合作&#xff0c;共68页&#xff0c;对于ICT领域投资者是难得好文。张亚勤、刘慈欣、周鸿祎、王飞跃、约翰.翰兹联合推荐这…

OpenCV学习笔记(十):图像金字塔Pyramid和图像缩放:pyrDown(),pyrUp(),resize()

OpenCV学习笔记&#xff08;十&#xff09;&#xff1a;图像金字塔Pyramid和图像缩放&#xff1a;pyrDown(),pyrUp(),resize() 一、图像金字塔定义&#xff1a; 图像金字塔是图像中多尺度表达的一种&#xff0c;最主要用于图像的分割&#xff0c;是一种以多分辨率来解释图像的…

量子纠缠和宇宙黑洞

2019年7月&#xff0c;量子纠缠&#xff08;两个光子&#xff09;照片首次公布2019年4月&#xff0c;宇宙黑洞&#xff08;质量为太阳的65亿倍&#xff09;照片首次公布来源&#xff1a;吴志刚科学网博客量子纠缠和宇宙黑洞&#xff0c;一个极小&#xff0c;一个极大&#xff0…

这些重大科技领域问题,听听专家怎么说

来源&#xff1a;科技日报从前不久结束的全英华人教授协会年会上了解到&#xff0c;目前人类面临的许多问题都可以通过扎实的科研创新和精准的技术应用予以解决&#xff1b;新的技术领域的出现&#xff0c;不代表传统技术方法都要丢弃&#xff1b;尽管摆在广大科技从业者面前的…

plt.fill_between用法

plt.fill_between用颜色填充两条曲线之间的区域plt.fill_between(x, y1, y2)&#xff0c;其中x是横坐标&#xff0c;y1和y2是两条曲线&#xff0c;这个函数的作用是用颜色填充y1和y2这两条曲线之间的区域。 该函数最常用的用法是已知均值曲线和标准差&#xff0c;画出标准差覆…

QT+OpenCV综合示例:载入、读取图片

QTOpenCV综合示例&#xff1a;载入、读取图片1、代码&#xff1a;2、运行结果&#xff1a;下载1 GitHub: 下载2 1、代码&#xff1a; 1&#xff09;opencv_imwrite_Q.pro 添加&#xff1a; INCLUDEPATH D:\opencv-3.1.0\opencv\build\includewin32:CONFIG(release, debug|re…

“算法战:DARPA下一代人工智能计划初见成效” 背景分析与初步研判

2018年9月&#xff0c;美国国防高级研究计划局&#xff08;DARPA&#xff09;宣布将出资20亿美元,用于开发新的人工智能技术。近日&#xff0c;DARPA副局长彼得海纳姆在华盛顿接受记者采访时说&#xff0c;DARPA的“下一代人工智能”&#xff08;AI Next&#xff09;计划在实施…

OpenCV学习笔记(十一):阈值化:threshold(),adaptivethreshold()

OpenCV学习笔记&#xff08;十一&#xff09;&#xff1a;阈值化&#xff1a;threshold(),adaptivethreshold() 一、定义&#xff1a; 1&#xff09;固定阈值操作 double threshold( InputArray src, // 输入图像&#xff0c;单通道 OutputArray dst, // 输出图像 double…

北京邮电大学刘伟教授:人机融合与混合智能的新应用场景

前言&#xff1a;本文是北京邮电大学人机交互与认知工程实验室主任、科技委人机融合智能组首席科学家刘伟教授就混合智能的产生、起源和新应用场景所做的深度阐述。第一部分是刘伟老师从新书《崛起的超级智能&#xff1a;互联网大脑如何影响科技未来》延伸的关于人机融合的思考…

VC++6.0怎么打开工程

点击文件→打开&#xff0c;选择工程所在文件夹&#xff0c;选择后缀名为dsp的文件打开即可。 若直接选择cpp后缀名打开&#xff0c;打开的只是cpp文件&#xff0c;而不是工程&#xff0c;此时VC右侧不会显示工程信息。

问题解决:QtCreator屏蔽指定警告:如C4819等

QT creator 频繁报出 &#xff0c;不好解决的错误如&#xff1a; warning: C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失 方法一&#xff1a;&#xff08;屏蔽此警告&#xff09; 在工程文件.pro里面添加 # disable C…

解析|2G~5G与未来天线技术!

来源&#xff1a;电子万花筒过去二十年&#xff0c;我们见证了移动通信从1G到4G LTE的转变。在这期间&#xff0c;通信的关键技术在发生变化&#xff0c;处理的信息量成倍增长。而天线&#xff0c;是实现这一跨越式提升不可或缺的组件。按照业界的定义&#xff0c;天线是一种变…

QT+OpenCV综合示例:图像混合(滑动条)

QTOpenCV综合示例&#xff1a;图像混合&#xff08;滑动条&#xff09;1、代码&#xff1a;2、运行结果&#xff1a;0&#xff09;Widget_op.ui &#xff08;界面文件&#xff09;设计&#xff1a; 1、代码&#xff1a; 1&#xff09;opencv_imwrite_Q.pro 添加&#xff1a;…

图说报告|智能技术群的“核聚变”推动智能+时代到来

来源&#xff1a;阿里研究院2019年政府工作报告正式提出了“智能”重要战略。5G、物联网、人工智能、数字孪生、云计算、边缘计算等智能技术群的融合与叠加就像“核聚变”&#xff0c;推动着万物互联迈向万物智能时代&#xff0c;进而带动了“智能”时代的到来&#xff0c;以智…

C++局部变量和全局变量的初始化

当局部变量被定义时&#xff0c;系统不会对其初始化&#xff0c;此时局部变量的初始值未定义&#xff0c;必须自行对其初始化。定义全局变量时&#xff0c;系统会自动初始化为下列值&#xff1a;

OpenCV学习笔记(十二):边缘检测:Canny(),Sobel(),Laplace(),Scharr滤波器

OpenCV学习笔记&#xff08;十二&#xff09;&#xff1a;边缘检测&#xff1a;Canny(),Sobel(),Laplace(),Scharr滤波器 1&#xff09;滤波&#xff1a;边缘检测的算法主要是基于图像强度的一阶和二阶导数&#xff0c;但导数通常对噪声很敏感&#xff0c;因此必须采用滤波器来…

微软转型里程碑:云计算收入首次超过Windows业务

来源&#xff1a;腾讯科技导语 微软云计算业务第二季度收入为114亿美元&#xff0c;实现了64%的营收增长&#xff0c;上年同期和上一季度的增幅分别为89%和73%。腾讯科技讯 据国外媒体报道&#xff0c;微软公司今日公布了二季度财报&#xff08;自然季度&#xff0c;下同&#…

OpenCV学习笔记(十三):霍夫变换:HoughLines(),HoughLinesP(),HoughCircles( )

OpenCV学习笔记&#xff08;十三&#xff09;&#xff1a;霍夫变换&#xff1a;HoughLines(),HoughLinesP(),HoughCircles( ) 1、霍夫线变换HoughLines() OpenCV支持三种不同的霍夫线变换&#xff0c;它们分别是&#xff1a; 1&#xff09;标准霍夫变换(Standard Hough Trans…

“如果没有IBM和其所提供的系统,我们就无法登上月球。”

来源&#xff1a;IBM中国“如果没有IBM和其所提供的系统&#xff0c;我们就无法登上月球。”——NASA飞行指挥官 Gena Kra1969年7月20日&#xff0c;就在距离阿姆斯特朗迈出“人类一大步”约122米的月球上空&#xff0c;登月舱里突然响起了刺耳的警报声。警报向NASA显示机载电脑…