Cv2.FloodFill(),水漫填充算法,是指用指定颜色填充与所选种子点像素的相连区域,常用于图像的分割,标记等。

函数原型:

        //// 摘要://     Fills a connected component with the given color.//// 参数://   image://     Input/output 1- or 3-channel, 8-bit, or floating-point image. It is modified//     by the function unless the FLOODFILL_MASK_ONLY flag is set in the second variant//     of the function. See the details below.////   seedPoint://     Starting point.////   newVal://     New value of the repainted domain pixels.////   rect://     Optional output parameter set by the function to the minimum bounding rectangle//     of the repainted domain.////   loDiff://     Maximal lower brightness/color difference between the currently observed pixel//     and one of its neighbors belonging to the component, or a seed pixel being added//     to the component.////   upDiff://     Maximal upper brightness/color difference between the currently observed pixel//     and one of its neighbors belonging to the component, or a seed pixel being added//     to the component.////   flags://     Operation flags. Lower bits contain a connectivity value, 4 (default) or 8, used//     within the function. Connectivity determines which neighbors of a pixel are considered.public static int FloodFill(InputOutputArray image, Point seedPoint, Scalar newVal, out Rect rect, Scalar? loDiff = default(Scalar?), Scalar? upDiff = default(Scalar?), FloodFillFlags flags = FloodFillFlags.Link4);

winform界面设计:

实现效果展示:

主要代码以及实现:

我的环境是 VS2015 Opencvsharp3

变量定义:

            //在 yVars.ImgOptions 下public struct FloodFill //水漫填充{// 水漫原图public static string Image;// 水漫填充颜色public static OpenCvSharp.Scalar fillColor = new Scalar();// 水漫种子点坐标public static OpenCvSharp.Point pointLocation = new OpenCvSharp.Point();// 线程启停信号public static ManualResetEvent getLocationEvent = new ManualResetEvent(false);// 种子点选取标志public static bool IsSelectPoint = false;public static int loDiff = 0;   // 水漫负差最大值public static int upDiff = 0;    // 水漫正差最大值//水漫后图片存取队列  用于撤销操作 水漫一次就往此list中添加一张结果图 public static List<OpenCvSharp.Mat> matList = new List<Mat>();// 更换原图标志位public static bool IsChangePic = false;}

主要方法:

        public static void ImgFloodFill(){// 在水漫图片的队列的最后一张图片上进行操作Mat pic = new Mat();int index = yVars.ImgOptions.FloodFill.matList.Count;pic = yVars.ImgOptions.FloodFill.matList[index - 1];Mat picOut = new Mat();// 水漫图像需要 BGR三通道图片Cv2.CvtColor(pic, picOut, ColorConversionCodes.BGRA2BGR);OpenCvSharp.Rect re = new Rect();// 正负差最大值对应的颜色Scalar loDiffColor = new OpenCvSharp.Scalar(yVars.ImgOptions.FloodFill.loDiff, yVars.ImgOptions.FloodFill.loDiff, yVars.ImgOptions.FloodFill.loDiff);Scalar upDiffColor = new OpenCvSharp.Scalar(yVars.ImgOptions.FloodFill.upDiff, yVars.ImgOptions.FloodFill.upDiff, yVars.ImgOptions.FloodFill.upDiff);// 将在图像种子点位置像素的正负差最大值之间的所有与种子点相连同的所有像素点设置成指定颜色Cv2.FloodFill(picOut, yVars.ImgOptions.FloodFill.pointLocation, yVars.ImgOptions.FloodFill.fillColor, out re,loDiffColor, upDiffColor, FloodFillFlags.Link8);// 比较水漫前后两张图是否一样  如果一样则不需要添加到队列 方便撤销操作 if (!yOthers.matIsEqual(pic, picOut)){yVars.ImgOptions.FloodFill.matList.Add(picOut);Form1.Instance.pbxFloodFill.Image = yImgConvert.MatToBitmap(picOut);}yVars.ImgOptions.FloodFill.IsSelectPoint = false;Form1.Instance.btnSelectPoint.BackColor = Color.Transparent;yVars.ImgOptions.FloodFill.pointLocation = new OpenCvSharp.Point(0, 0);Form1.Instance.tbxFlood_x.Text = "0";Form1.Instance.tbxFlood_y.Text = "0";yVars.ImgOptions.FloodFill.getLocationEvent.Reset();}// 获取种子坐标线程// 在点击选择点位之后 当鼠标进入picturebox后 启动下面线程 // 当在picturebox上点击鼠标时 暂停下面线程 并将此时鼠标点击位置设置成水漫种子点public static Thread GetLocationTask = new Thread(() =>{while (true){int MX = 0, MY = 0;OpenCvSharp.Mat mm = new OpenCvSharp.Mat();mm = yImgConvert.ImageToMat(Form1.Instance.pbxFloodFill.Image);Form1.Instance.Invoke(new Action(() =>{// 鼠标相对于picturebox的位置MX = Form1.Instance.pbxFloodFill.PointToClient(Control.MousePosition).X;MY = Form1.Instance.pbxFloodFill.PointToClient(Control.MousePosition).Y;if (MX <= Form1.Instance.pbxFloodFill.Width && MY <= Form1.Instance.pbxFloodFill.Height && MX > 0 && MY > 0){Form1.Instance.tbxFlood_x.Text = MX.ToString();Form1.Instance.tbxFlood_y.Text = MY.ToString();// 图片是经过缩放后再放入picturebox中 // 大小并不一样 所以需要将相对于picturebox的坐标 转换成相对于对应图片坐标double xx = MX * mm.Width / Form1.Instance.pbxFloodFill.Width;double yy = MY * mm.Height / Form1.Instance.pbxFloodFill.Height;yVars.ImgOptions.FloodFill.pointLocation = new OpenCvSharp.Point(xx, yy);}else{Form1.Instance.tbxFlood_x.Text = "0";Form1.Instance.tbxFlood_y.Text = "0";yVars.ImgOptions.FloodFill.pointLocation = new OpenCvSharp.Point(0, 0);}}));yVars.ImgOptions.FloodFill.getLocationEvent.WaitOne();Thread.Sleep(100);}});
        // 判断两张多通道图片是否完全一样public static bool matIsEqual(Mat mat1, Mat mat2){if (mat1.Empty() && mat2.Empty()){return true;}if (mat1.Cols != mat2.Cols || mat1.Rows != mat2.Rows || mat1.Dims() != mat2.Dims()){return false;}if (mat1.Size() != mat2.Size() || mat1.Channels() != mat2.Channels() || mat1.Type() != mat2.Type()){return false;}if (mat1.Total() * mat1.ElemSize() != mat2.Total() * mat2.ElemSize()){return false;}Mat tempMat = new Mat();Cv2.BitwiseXor(mat1, mat2, tempMat);Mat[] mm = Cv2.Split(tempMat);foreach (Mat m1 in mm){if (Cv2.CountNonZero(m1) != 0)return false;}return true;}

主要控件事件:

        // 选择水漫填充颜色private void btnSelectFloodColor_Click(object sender, EventArgs e){ColorDialog cc = new ColorDialog();if (cc.ShowDialog() == DialogResult.OK){yVars.ImgOptions.FloodFill.fillColor = OpenCvSharp.Scalar.FromRgb(cc.Color.R, cc.Color.G, cc.Color.B);palFloodColor.BackColor = cc.Color;}}// 选择点位点击事件private void btnSelectPoint_Click(object sender, EventArgs e){if (yVars.ImgOptions.FloodFill.Image == null){YXH._01.yMessagebox.Show_CN("未选择图片");return;}if (yVars.ImgOptions.FloodFill.IsSelectPoint == false){yVars.ImgOptions.FloodFill.IsSelectPoint = true;btnSelectPoint.BackColor = Color.Green;yVars.ImgOptions.FloodFill.IsChangePic = false;btnSelectFloodfill.Enabled = false;}else{yVars.ImgOptions.FloodFill.IsSelectPoint = false;btnSelectPoint.BackColor = Color.Transparent;}}// 点击选择点位按钮后 当鼠标进入picturebox后启动获取鼠标点位的线程private void pbxFloodFill_MouseEnter(object sender, EventArgs e){if (yVars.ImgOptions.FloodFill.IsSelectPoint == false)return;if (pbxFloodFill.Image == null)return;yVars.ImgOptions.FloodFill.getLocationEvent.Set();if (!yImgOptions.GetLocationTask.IsAlive)yImgOptions.GetLocationTask.Start();}// picturebo 点击时 暂停线程 画出选择点位private void pbxFloodFill_Click(object sender, EventArgs e){if (yVars.ImgOptions.FloodFill.pointLocation != null && yVars.ImgOptions.FloodFill.IsSelectPoint == true && yVars.ImgOptions.FloodFill.pointLocation != new OpenCvSharp.Point(0, 0)){OpenCvSharp.Mat spMat = new OpenCvSharp.Mat();spMat = yImgConvert.ImageToMat(Form1.Instance.pbxFloodFill.Image);OpenCvSharp.Cv2.Circle(spMat, yVars.ImgOptions.FloodFill.pointLocation, 0, OpenCvSharp.Scalar.Red, 2, LineTypes.AntiAlias);pbxFloodFill.Image = yImgConvert.MatToBitmap(spMat);btnSelectFloodfill.Enabled = true;}yVars.ImgOptions.FloodFill.getLocationEvent.Reset();yVars.ImgOptions.FloodFill.IsSelectPoint = false;btnSelectPoint.BackColor = Color.Transparent;}// 图像复原private void btnResetPic_Click(object sender, EventArgs e){if (!string.IsNullOrEmpty(yVars.ImgOptions.FloodFill.Image))pbxFloodFill.Image = new Bitmap(yVars.ImgOptions.FloodFill.Image);}// 撤销操作 从水漫图片队列中 选择倒数第二张显示 并删除最后一张private void btnRepeal_Click(object sender, EventArgs e){int index = 0;index = yVars.ImgOptions.FloodFill.matList.Count;if (index <= 1)return;else if (index > 1){yVars.ImgOptions.FloodFill.matList.RemoveAt(index - 1);index = yVars.ImgOptions.FloodFill.matList.Count;Form1.Instance.pbxFloodFill.Image = yImgConvert.MatToBitmap(yVars.ImgOptions.FloodFill.matList[index - 1]);}}

c#winform利用opencvsharp的Floodfill实现类似PS魔棒功能相关推荐

  1. 浮点数相加php,利用php怎么实现一个浮点数精确运算功能

    利用php怎么实现一个浮点数精确运算功能 发布时间:2020-12-15 16:06:03 来源:亿速云 阅读:94 作者:Leah 今天就跟大家聊聊有关利用php怎么实现一个浮点数精确运算功能,可能 ...

  2. C# 类似PS的魔棒工具(1)

    最近一段时间在开发一个画图软件,其中需要实现魔棒功能.网上浏览了一圈,没有找到.苦思之后,终于开窍了:.思路是:先用漫水填充算法, 获得一张连通区域的二值图.然后对这幅图进行边缘检测,获取边缘.如果使 ...

  3. C#/Csharp桌面应用开发小作业小程序,类似微信登录功能的小软件

    (七) 微信APP是一款非常流行的及时通讯类应用软件,请利用所学的桌面应用开发知识,仿照完成一个类似微信登录功能的小软件,功能要求如下所示,最终效果见Demo文件夹: 软件需求及编码提示:  该软件 ...

  4. 利用语音Modem实现电话点播和留言功能

    利用语音Modem实现电话点播和留言功能 (加入日期:2003-11-8 点击数:9812) [收藏文章][对此文发表评论][编程爱好者论坛][保存文章至硬盘][打印文章] id="nadf ...

  5. python头像右上角加红色数字_利用python实现微信头像加红色数字功能

    通过Python实现将你的 QQ 头像(或者微博头像)右上角加上红色的数字,类似于微信未读信息数量那种提示效果. 类似于图中效果 实现过程: 准备两张图片如下: 使用PIL图像处理库,导入moudle ...

  6. VC++ 利用MFC的CWindowDC类实现画线功能 在桌面窗口中画线 绘制彩色线条 CPen nPenStyle nWidth crColor

    目录 利用MFC的CWindowDC类实现画线功能 在桌面窗口中画线 绘制彩色线条 CPen nPenStyle nWidth crColor 接上:VC++ 绘制线条 OnLButtonDown函数 ...

  7. 利用python实现短信和电话提醒功能

    有时候,我们需要程序帮我们自动检测某些事件的发生 这个需求是广泛存在的 因此,这里整理了利用python实现短信和电话提醒功能的方法 主要需要完成以下4个步骤: - 安装核心库:twilio - 注册 ...

  8. python提醒事件_利用python实现短信和电话提醒功能的例子

    有时候,我们需要程序帮我们自动检测某些事件的发生 这个需求是广泛存在的 因此,这里整理了利用python实现短信和电话提醒功能的方法 主要需要完成以下4个步骤: - 安装核心库:twilio - 注册 ...

  9. 利用传感器实现微信的摇一摇功能

    android开发利用传感器实现微信的摇一摇功能(zz) 现在的不少应用都用到了摇动手机改变内容的功能,比如微信中的"摇一摇"功能.前两天要实现这个功能,稍微看了一下关于传感器Se ...

  10. VC++ 绘制线条 OnLButtonDown函数(DrawView.cpp) 利用SDK全局函数实现画线功能 利用MFC的CDC类实现画线功能 利用MFC的CClientDC类实现画线功能

    目录 绘制线条 OnLButtonDown函数(DrawView.cpp) 利用SDK全局函数实现画线功能 利用MFC的CDC类实现画线功能 利用MFC的CClientDC类实现画线功能 接上:VC+ ...

最新文章

  1. 利用UltimateAndroid框架进行快速开发
  2. 李彦宏称AI可让人们获得永生
  3. c#接口和抽象类对比学习
  4. HTML为什么认为“ chucknorris”是一种颜色?
  5. 研发流程与项目管理之关系
  6. 人很臭尽量往香里去做...
  7. 【设计模式】设计模式C++编程实现之观察者模式(ObserverPattern)
  8. 30岁的你,目标工资是多少?
  9. emacs自动连接mysql数据库
  10. android图片 垂直排列,Android图片切换特效示例:水平百叶窗、垂直百叶窗、马赛克...
  11. 《JSP实用教程(第2版)/耿祥义》错误之非必要导入包
  12. 计算机主板 华硕 游戏用,华硕Z390-A大师主板,带你畅享极致游戏体验-华硕主板bios设置...
  13. 界面画好了如何开发软件_如何做儿童类APP?来看英语流利说的实战经验总结!...
  14. 慧翔PMP培训及感想
  15. 取地址符和指针*的认识
  16. 新时代知识产权创新发展与严格保护_保护知识产权?宣传强化治理——东安街道团结社区新时代文明实践站大力宣传《知识产权法》...
  17. UE4 角色添加武器后 移动出现漂移
  18. 并发编程——Forkjoin设计模式原理
  19. Unity3D Shader 新手教程(5/6) —— Bumped Diffuse Shader
  20. 天干地支与阴阳五行的关系

热门文章

  1. python的help函数如何使用
  2. hexo yilia个性化样式设置
  3. uni-app编译报caniuse-lite is outdated
  4. 【微信退款】Java实现微信APP退款和JSAPI退款流程
  5. Devcpp新建文件自动添加一定代码
  6. Mysql持久性的实现
  7. 微信自动投票的php代码
  8. java 基础:方法/函数
  9. MySQL 英文格式日期转换
  10. 秀米排版,从入门到入土(一)