图像分割-Grabcut法(C#)
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。
本文的VB版本请访问:图像分割-Grabcut法-CSDN博客
GrabCut是一种基于图像分割的技术,它可以用于将图像中的前景和背景分离。在实现中,GrabCut算法通常需要使用高斯混合模型(GMM)来建立前景和背景的概率分布,以便更好的估计像素的标签。同时,还需要考虑如何处理边界处的像素,以避免边界处的像素被错误地分类。GrabCut算法在图像分割中有着广泛的应用,例如人像分割、物体抠图等。
EmguCV使用CvInvoke.GrabCut方法来执行GrabCut算法,该方法声明如下:
public static void GrabCut(
IInputArray img,
IInputOutputArray mask,
Rectangle rect,
IInputOutputArray bgdModel,
IInputOutputArray fgdModel,
int iterCount,
GrabcutInitType type
)
参数说明:
- img:输入输出的图像,必须是三通道彩色图像。
- mask:指定的掩码图像,必须是单通道灰度图像,并且与输入图像具有相同的尺寸。可以传入0-3的值,分别为:0表示明显为背景的像素、1表示冥相位前景的像素、2表示可能为背景的像素、3表示可能为前景的像素。
- rect:指定的矩形框,用于定位大概率可能为前景目标的位置。
- bgdModel:背景模型,必须是单通道浮点型Mat。
- fgdModel:前景模型,必须是单通道浮点型Mat。
- iterCount:迭代次数,用于控制算法的收敛性。
- type:GrabCut算法初始化类型,可以选择GrabCutInitType.WithRect或GrabCutInitType.WithMask,分别表示根据提供的矩形初始化或根据掩码初始化。
该方法没有返回值,而是直接在mask图像上进行前景分割操作,最终获得的mask包含0-3的值,含义如参数中说明。
//Grabcut法 private void Button5_Click(object sender, EventArgs e){Mat m = new Mat("C:\\learnEmgucv\\tower.jpg", ImreadModes.AnyColor);Mat result = new Mat();Mat bg = new Mat();Mat fg = new Mat();Rectangle rect = new Rectangle(80, 30, 680, 450);CvInvoke.GrabCut(m, result, rect, bg, fg, 1, GrabcutInitType.InitWithRect);//输出的result只有4个值://0:确定背景//1:确定前景//2:可能背景//3:可能前景//演示框选范围CvInvoke.Rectangle(m, rect, new MCvScalar(255, 255, 255), 1);ImageBox1.Image = m;//标记区域Matrix<byte> matr = new Matrix<byte>(result.Rows, result.Cols);result.CopyTo(matr);for (int i = 0; i < matr.Cols; i++){for (int j = 0; j < matr.Rows; j++){//将确定背景和可能背景标记为0,否则为255if (matr[j, i] == 0 || matr[j, i] == 2)matr[j, i] = 0;elsematr[j, i] = 255;}}Mat midm = new Mat();midm = matr.Mat;//显示标记的图像CvInvoke.Imshow("midm", midm);//灰度转为彩色Mat midm1 = new Mat();CvInvoke.CvtColor(midm, midm1, ColorConversion.Gray2Bgr);Mat mout = new Mat();//And运算CvInvoke.BitwiseAnd(m, midm1, mout);CvInvoke.Imshow("mout", mout);}
输出结果如下图所示:

图8-5 Grabcut法分离前景
//Grabcut法 private void Button6_Click(object sender, EventArgs e){Mat m = CvInvoke.Imread("C:\\learnEmgucv\\tower.jpg", ImreadModes.Color);Mat result = new Mat();Mat bg = new Mat();Mat fg = new Mat();Rectangle rect = new Rectangle(80, 30, 680, 450);CvInvoke.GrabCut(m, result, rect, bg, fg, 5, GrabcutInitType.InitWithRect);Image<Bgr, byte> src = m.ToImage<Bgr, byte>();Image<Bgr, byte> dst = new Image<Bgr, byte>(new Size(src.Width, src.Height));Image<Gray, byte> mask = result.ToImage<Gray, byte>();//直接操作Image像素点for (int i = 0; i < src.Rows; i++){for (int j = 0; j < src.Cols; j++){//如果是确定前景和可能前景,直接保留原像素点颜色,否则为黑色if (mask.Data[i, j, 0] == 1 || mask.Data[i, j, 0] == 3){dst.Data[i, j, 0] = src.Data[i, j, 0];dst.Data[i, j, 1] = src.Data[i, j, 1];dst.Data[i, j, 2] = src.Data[i, j, 2];}else{dst.Data[i, j, 0] = 0;dst.Data[i, j, 1] = 0;dst.Data[i, j, 2] = 0;}}}ImageBox1.Image = dst;}
输出结果如下图所示:

图8-6 Grabcut法分离前景
//标记为确定前景,这里使用InitWithMask 参数private void Button7_Click(object sender, EventArgs e){Mat m = new Mat("c:\\learnEmgucv\\lena.jpg", ImreadModes.AnyColor);Mat mask = new Mat();Mat bg = new Mat();Mat fg = new Mat();Rectangle rect = new Rectangle(80, 30, 340, 480);//使用前景为全白色Mat m1 = new Mat("c:\\learnEmgucv\\lena_fillwhite.jpg", ImreadModes.Grayscale);Mat mask1 = new Mat();//二值化CvInvoke.Threshold(m1, mask1, 250, 1, ThresholdType.Binary);CvInvoke.Rectangle(m, rect, new MCvScalar(255, 255, 255), 1);//标记之后再调用GrabCut,使用InitWithMask参数CvInvoke.GrabCut(m, mask1, rect, bg, fg, 2, GrabcutInitType.InitWithMask);Matrix<byte> matrx = new Matrix<byte>(mask1.Rows, mask1.Cols);mask1.CopyTo(matrx);for (int i = 0; i < matrx.Cols; i++)for (int j = 0; j < matrx.Rows; j++)if (matrx[i, j] == 0 || matrx[i, j] == 2)matrx[i, j] = 0;elsematrx[i, j] = 255;Mat midm2 = new Mat();midm2 = matrx.Mat;Mat midm1 = new Mat();CvInvoke.CvtColor(midm2, midm1, ColorConversion.Gray2Bgr);Mat mout = new Mat();CvInvoke.BitwiseAnd(m, midm1, mout);CvInvoke.Imshow("mout", mout);}
输出结果如下图所示:

图8-7 Grabcut法分离前景
由于.net平台下C#和vb.NET很相似,本文也可以为C#爱好者提供参考。
学习更多vb.net知识,请参看vb.net 教程 目录
相关文章:
图像分割-Grabcut法(C#)
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 本文的VB版本请访问:图像分割-Grabcut法-CSDN博客 GrabCut是一种基于图像分割的技术,它可以用于将图像中的…...
C# WPF上位机开发(Web API联调)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 很多时候,客户需要开发的不仅仅是一个上位机系统,它还有其他很多配套的系统或设备,比如物流小车、立库、数字孪…...
c语言:用结构体求平均分|练习题
一、题目 用c语言的结构体,求4位学生成绩的平均分 如图: 二、代码截图【带注释】 三、源代码【带注释】 #include <stdio.h> float aver();//声明平均分函数 void printScore();//声明打印函数 //设置结构体, struct student { …...
echarts 仪表盘进度条 相关配置
option {series: [{type: gauge,min: 0,//最大值max: 100, //最小值startAngle: 200,//仪表盘起始角度。圆心 正右手侧为0度,正上方为90度,正左手侧为180度。endAngle: -20,//仪表盘结束角度splitNumber: 100, //仪表盘刻度的分割段数itemStyle: {color…...
Simpy:Python之离散时间序列仿真
Simpy:Python之离散时间序列仿真 文章目录 Simpy:Python之离散时间序列仿真简介基本使用语法简单案例在数据中心中的应用案例 简介 下载地址网站: https://pypi.org/project/simpy/ 有关教程网站: https://simpy.readthedocs.…...
连接GaussDB(DWS)报错:Invalid or unsupported by client SCRAM mechanisms
用postgres方式连接GaussDB(DWS)报错:Invalid or unsupported by client SCRAM mechanisms 报错内容 [2023-12-27 21:43:35] Invalid or unsupported by client SCRAM mechanisms org.postgresql.util.PSQLException: Invalid or unsupported by client SCRAM mec…...
汽车标定技术(十四)--标定数据固化方法简介
目录 1.标定数据固化方法 1.1 基于XCP固化 1.2 基于UDS固化 2. 具体实现形式 2.1 CAN...
2024年关键技术发展战略趋势前瞻
技术趋势在不断变化,但总的趋势是技术日益深入人类生活的方方面面,这些趋势可能会对未来的科技发展和人类生活产生深远影响,以下是预计今年将塑造未来的一些关键技术趋势。 更多的人将采用人工智能和机器学习 人工智能(AI)和机器学习(ML)不…...
Java程序设计——GUI设计
一、目的 通过用户图形界面设计,掌握JavaSwing开发的基本方法。 二、实验内容与设计思想 实验内容: 课本验证实验: Example10_6 图 1 Example10_7 图 2 图 3 Example10_15 图 4 设计思想: ①学生信息管理系统:…...
three.js Raycaster(鼠标点击选中模型)
效果: 代码: <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div><div class"box-right"…...
Springboot整合RocketMQ 基本消息处理
目录 1. 同步消息 2. 异步消息 3. 单向消息 4. 延迟消息 5. 批量消息 6. 顺序消息 7. Tag过滤 导入依赖 <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId></dependency> …...
红外传感器深入解析
引言 宇宙间的任何物体只要其温度超过零度就能产生红外辐射,事实上同可见光一样,其辐射能够进行折射和反射,这样便产生了红外技术,利用红外光探测器因其独有的优越性而得到广泛的重视,并在军事和民用领域得到了广泛…...
18、Kubernetes核心技术 - InitContainer(初始化容器)
目录 一、概述 二、使用InitContainer 一、概述 InitContainer即初始化容器,是 K8S官方为我们提供的一个可以用来判断环境是否已经满足运行 Pod 应用前所需要的条件。 比如我们有一个应用,需要部署到Tomcat环境,那么在部署这个应用Pod之前…...
electron进程通信之预加载脚本和渲染进程对主进程通信
主进程和预加载脚本通信 主进程 mian,js 和预加载脚本preload.js,在主进程中创建预加载脚本, const createWindow () > {// Create the browser window.const mainWindow new BrowserWindow({width: 300,height: 300,// 指定预加载脚本webPreferences: {preload: path.j…...
如何有效使用 .gitignore 文件
在任何使用 Git 的软件项目中,.gitignore 文件都是一个必不可少的工具。它帮助开发者定义哪些文件和目录应该被 Git 忽略,从而保持代码库的整洁和管理的简便性。 什么是 .gitignore? .gitignore 文件是一个文本文件,您可以在其中指…...
大数据毕设分享 flink大数据淘宝用户行为数据实时分析与可视化
文章目录 0 前言1、环境准备1.1 flink 下载相关 jar 包1.2 生成 kafka 数据1.3 开发前的三个小 tip 2、flink-sql 客户端编写运行 sql2.1 创建 kafka 数据源表2.2 指标统计:每小时成交量2.2.1 创建 es 结果表, 存放每小时的成交量2.2.2 执行 sql &#x…...
大语言模型训练数据集
大语言模型的数据集有很多,以下是一些常用的: - 中文维基百科:这是一个包含大量中文文本的数据集,可用于训练中文语言模型。 - 英文维基百科:这是一个包含大量英文文本的数据集,可用于训练英文语言模型。 …...
python的课后练习总结4(while循环)
for循环用于针对序列中的每个元素的一个代码块。 while循环是不断的运行,直到指定的条件不满足为止。 while 条件: 条件成立重复执行的代码1 条件成立重复执行的代码2 …….. i 1while i < 5:print(i)i i 11、使用wh…...
Flink Connector 开发
Flink Streaming Connector Flink是新一代流批统一的计算引擎,它需要从不同的第三方存储引擎中把数据读过来,进行处理,然后再写出到另外的存储引擎中。Connector的作用就相当于一个连接器,连接Flink计算引擎跟外界存储系统。Flin…...
Golang leetcode707 设计链表 (链表大成)
文章目录 设计链表 Leetcode707不使用头节点使用头节点 推荐** 设计链表 Leetcode707 题目要求我们通过实现几个方法来完成对链表的各个操作 由于在go语言中都为值传递,(注意这里与值类型、引用类型的而区别),所以即使我们直接在…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...
tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...
