OpenCV学习(4.15) 基于 GrabCut 算法的交互式前景提取

1. 目标

在这一章当中

  • 我们将看到 GrabCut 算法来提取图像中的前景
  • 我们将为此创建一个交互式应用程序。

2. 理论

GrabCut 算法由英国剑桥微软研究院 Carsten Rother,Vladimir Kolmogorov和Andrew Blake发明,并在他们的论文“GrabCut”:使用迭代图切割中提出。该算法需要最少的人工交互做前景提取,被称为 GrabCut。

从用户角度来看,该算法是如何工作的呢?最初用户在前景区域周围绘制一个矩形(该矩形需要完全框住所有的前景区域) 。然后算法对其进行迭代分割,得到最佳结果。但在某些情况下,分割的不是那么理想,比如说,它可能把一些前景区域标成了背景,或者反过来。如果发生了这样的情况,用户需要进行仔细的修正。只要在有错误结果的地方“划一下”就行了。“划一下”基本的意思是说,*"嘿,这个区域应该是前景,你标记它为背景,在下一次迭代中更正它。"* 或者如果区域是背景,也如此类推。然后再下一次迭代中,你就会得到更好的结果。

见下图。第一名球员和足球被包围在一个蓝色矩形中。然后进行一些具有白色笔划(表示前景)和黑色笔划(表示背景)的最终修饰。我们得到了一个很好的结果。

那背景会发生什么?

  • 用户输入矩形。这个矩形之外的所有东西都将被视为确定的背景(这就是之前提到的矩形应该包括所有对象的原因)。矩形内的一切都是未知的。类似地,任何指定前景和背景的用户输入都被视为硬标签,这意味着它们不会在过程中发生变化。
  • 计算机根据我们提供的数据进行初始标记。它标记前景和背景像素(或硬标记)
  • 现在使用高斯混合模型(GMM)来模拟前景和背景。
  • 根据我们提供的数据,GMM 学习并创建新的像素分布。也就是说,未知像素被标记为可能的前景或可能的背景,这取决于其在颜色统计方面与其他硬标记像素的关系(它就像聚类一样)。
  • 从该像素分布构建图形。图中的节点是像素。添加了另外两个节点,源节点和 Sink 节点。每个前景像素都连接到源节点,每个背景像素都连接到 Sink 节点。
  • 连接像素到源节点/端节点的边的权重由像素是前景/背景的概率来定义。像素之间的权重由边缘信息或像素相似性定义。如果像素颜色存在较大差异,则它们之间的边缘将获得较低的权重。
  • 然后使用 mincut 算法来分割图形。它将图形切割成两个分离源节点和汇聚节点,具有最小的成本函数。成本函数是被切割边缘的所有权重的总和。切割后,连接到 Source 节点的所有像素变为前景,连接到 Sink 节点的像素变为背景。
  • 该过程一直持续到分类收敛为止。

如下图所示

现在我们使用 OpenCV 进行抓取算法。 OpenCV 具有此功能, cv.grabCut() 。我们将首先看到它的参数:

  • img - 输入图像
  • mask - 这是一个掩膜图像,我们指定哪些区域是背景,前景或可能的背景/前景等。它由以下标志完成, **cv.GC_BGD , cv.GC_FGD , cv.GC_PR_BGD , cv.GC_PR_FGD**,或简单地将 0,1,2,3 传递给图像。
  • rect - 它是一个矩形的坐标,包括格式为(x,y,w,h)的前景对象
  • bdgModel , fgdModel - 这些是内部算法使用的数组。您只需创建两个大小为(n = 1.65)的 np.float64 类型零数组。
  • iterCount - 算法运行的迭代次数。
  • 模式 - 它应该是 **cv.GC_INIT_WITH_RECT**或 **cv.GC_INIT_WITH_MASK**或合并后决定我们是否正在绘图矩形或最终修饰笔画。

GrabCut是一种基于图割(Graph Cut)的交互式前景提取算法,它由微软研究院的Carsten Rother、Vladimir Kolmogorov和Andrew Blake在2004年提出。GrabCut算法利用了图割技术来优化图像分割,使得分割结果既准确又高效。与传统的图像分割方法相比,GrabCut能够更好地处理复杂背景和透明物体,同时允许用户交互式地修正分割结果。
GrabCut算法的基本步骤如下:

  • 1. **用户交互**:用户在图像中画一个矩形框,框出想要提取的前景对象。这个矩形框内的区域被认为是可能的前景,而矩形框外的区域被认为是背景。
  • 2. **初始化**:算法将矩形框内的像素分为两类:前景(T)和背景(B)。矩形框外的像素被初始化为确定背景(B)。
  • 3. **构建图模型**:GrabCut构建了一个图模型,其中节点代表图像中的像素和边界像素,边代表像素之间的关系。每个像素节点与一个源节点(source node)和一个汇节点(sink node)相连,边的权重由像素之间的相似度决定。
  • 4. **能量最小化**:通过图割算法(如最大流最小割算法)来最小化能量函数,能量函数考虑了像素之间的相似性和光滑性。在最小化过程中,图中的边被切割,从而将像素分为前景和背景。
  • 5. **迭代优化**:GrabCut算法迭代地更新像素的前景和背景概率,并重新进行图割,直到达到收敛。
  • 6. **用户修正**:用户可以标记错误分类的像素,GrabCut会根据用户的反馈重新计算概率和进行图割,以改进分割结果。
  • 7. **输出结果**:最终,GrabCut算法输出一个前景掩码,其中前景像素被标记为白色,背景像素被标记为黑色。

GrabCut算法的优点是它能够处理较为复杂的场景,并且用户交互简单,可以快速得到满意的分割结果。此外,它的计算效率较高,适合于实时应用。然而,GrabCut算法对于物体的轮廓和纹理较为敏感,对于边缘模糊或纹理复杂的区域可能分割效果不佳。
 

首先让我们看看矩形模式。我们加载图像,创建一个类似的蒙版图像。我们创建 fgdModel 和 bgdModel 。我们给出矩形参数。这一切都是直截了当的。让算法运行 5 次迭代。模式应该是 _cv.GC_INIT_WITH_RECT_,因为我们使用的是矩形。然后运行抓取。它修改了蒙版图像。在新的掩模图像中,像素将标记有四个标记,表示背景/前景,如上所述。因此,我们修改掩模,使得所有 0 像素和 2 像素都被置为 0(即背景),并且所有 1 像素和 3 像素被置为 1(即前景像素)。现在我们的最后面具准备好了。只需将其与输入图像相乘即可得到分割后的图像。

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('messi5.jpg')
mask = np.zeros(img.shape[:2],np.uint8)
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
rect = (50,50,450,290)
cv.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv.GC_INIT_WITH_RECT)
mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img = img*mask2[:,:,np.newaxis]
plt.imshow(img),plt.colorbar(),plt.show()

结果如下:

哎呀,梅西的头发都没了。谁喜欢没头发的梅西? 我们需要把它带回来。所以我们将用 1 像素(确定的前景)给出一个精细的修饰。与此同时,有些地方已经出现了我们不想要的图片,还有一些标识。我们需要删除它们。在那里我们提供一些 0 像素的修饰(确定背景)。因此,我们如前所述地调整了结果掩膜。

我实际上做的是,在绘画应用程序中打开了输入图像,并在图像中添加了另一层。在画中使用画笔工具,我在这个新图层上标记了不需要的白色背景(如徽标,地面等)以及黑色的前景(头发,鞋子,球等)。然后用灰色填充剩余的背景。然后在 OpenCV 中加载该掩模图像,编辑我们在新添加的掩模图像中使用相应值的原始掩模图像。查看以下代码:

# newmask is the mask image I manually labelled
newmask = cv.imread('newmask.png',0)
# wherever it is marked white (sure foreground), change mask=1
# wherever it is marked black (sure background), change mask=0
mask[newmask == 0] = 0
mask[newmask == 255] = 1
mask, bgdModel, fgdModel = cv.grabCut(img,mask,None,bgdModel,fgdModel,5,cv.GC_INIT_WITH_MASK)
mask = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img = img*mask[:,:,np.newaxis]
plt.imshow(img),plt.colorbar(),plt.show()

看下面的结果: 

 

 就是这样了。这里不是在 rect 模式下初始化,而是直接进入掩膜模式。只需用 2 像素或 3 像素(可能的背景/前景)标记蒙版图像中的矩形区域。然后像我们在第二个例子中那样用 1 像素标记我们的 sure_foreground。然后直接应用具有掩膜模式的 grabCut 函数。

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

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

相关文章

LLM之RAG实战(四十)| 使用LangChain SQL Agent和MySQL搭建多层RAG ChatBot

在传统的意义上,RAG 主要是从文档中检索用户想要的数据,从而提高大模型的能力,减少幻觉问题。今天,我们从另一个维度介绍RAG,RAG不从文档中获取数据,而是从MySQL数据库检索数据。我们可以使用LangChain SQL…

Vue40-vueComponent构造函数

一、组件的本质:VueComponent构造函数 组件的本质是:构造函数 二、每一次调用vue.extend,返回的事一个全新的 VueComponent VueComponent的源码如下: 三、组件中的this 组件中的this是VueComponent实例对象,结构和vm…

如果给电商系统颜值搞排名,我觉得淘宝千牛系统是天花板了。

淘宝的商家操作界面-千牛系统经过多年的迭代,无论从颜值上、功能上还是用户体验上都是行业天花板的存在,我截图软件上的一些图给大家分享下。

网络编程之XDP和TC

一、TC之于XDP 在前面分析过XDP,今天简单分析一下与其相关的TC,即traffic control,流量控制。在分析XDP时知道其只能用于ingress方向触发,而TC却可以在两个方向即ingress和egress方向触发。也可以简单理解成它可以同时钩住进出两个方向的数据…

foxmai邮箱使用技巧图文板简单容易,服务器配置密钥配置

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持&#xf…

手把手教你实现条纹结构光三维重建(2)——条纹解码

在第一讲中,我们讲到了条纹的生成,这一讲,我们将实现条纹的解码。我们这里的解码技术很简单,即高低频倍数解码,详细的论文可以参考:《Temporal phase unwrapping algorithms for fringe projection profilo…

基于 Transformer 的大语言模型

语言建模作为语言模型(LMs)的基本功能,涉及对单词序列的建模以及预测后续单词的分布。 近年来,研究人员发现,扩大语言模型的规模不仅增强了它们的语言建模能力,而且还产生了处理传统NLP任务之外更复杂任务…

4-字符串-11-反转字符串-LeetCode344

4-字符串-11-反转字符串-LeetCode344 LeetCode: 题目序号344 更多内容欢迎关注我(持续更新中,欢迎Star✨) Github:CodeZeng1998/Java-Developer-Work-Note 技术公众号:CodeZeng1998(纯纯技术文&#xff0…

认识一些分布函数-Frechet分布及其应用

1. 何为Frechet分布 Frechet分布也称为极值分布(EVD)类型II,用于对数据集中的最大值进行建模。它是四种常用极值分布之一。另外三种是古贝尔分布、威布尔分布和广义极值分布(Gumbel Distribution, the Weibull Distribution and the Generalized Extreme Value Distributi…

亿达中国武汉园区入选“武汉市科技金融工作站”及“武汉市线下首贷服务站”

近日,武汉市2024科技金融早春行活动在深交所湖北资本市场培育基地举行。会上,第四批武汉市科技金融工作站试点单位名单及第五批武汉地区金融系统线下首贷服务站名单正式公布,武汉软件新城成功入选上述两个名单。 为缓解科技型企业融资难题&a…

vue2+echarts实现简易的2d地图效果

背景 公司的一个可视化数据大屏里面,有一个使用echarts实现的2d地图。不是我开发的,在此记录一下实现过程以及一些扩展解构。应该是从哪个航空航线图改动了一下,效果看起来还是可以的。 效果预览 版本 vue版本使用的是"^2.6.12"…

我要成为算法高手-双指针篇

目录 什么是双指针?问题1:移动零问题2:复写零问题3:快乐数问题4:盛最多水的容器问题5:有效三角形个数问题6:查找总价格和为目标值的两个商品(两数之和)问题7:三数之和问题8:四数之和…

私域流量新利器:大模型+智慧客服+知识智能多管齐下,效果倍增!

前言 随着互联网环境的发展,线上市场竞争日益激烈,越来越多的企业开始关注私域流量的运营和管理——将品牌的用户数据在品牌官网、微信公众号、APP等自有平台上进行管理和运营,通过与用户建立深入的关系和互动,提升用户黏性、增强…

LNMP搭建:Linux+Nginx+MySQL+PHP

关闭防火墙和核心防护,使用一台机器Node1搭建LNMP systemctl stop firewalld; setenforce 0 所需源码包:可以去官网下载 编译Nginx 创建/data,在/data/下放源码包 [rootNode1 ~]#:mkdir /data;cd /data 安装依赖包 [rootNode1 data]#:yum …

第一个SpringBoot程序

第一个SpringBoot程序 目录介绍 当我们创建了一个SpringBoot项目之后,会出现如下的目录结构 SpringBoot项⽬有两个主要的⽬录: src/main/java: Java源代码 src/main/resources:为静态资源或配置⽂件: /static:静态资源⽂件夹,⽐…

Spring Cloud Netflix 之 Ribbon

前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家:https://www.captainbed.cn/z ChatGPT体验地址 文章目录 前言前言1、负载均衡1.1、服务端负载均衡1.2、客户端负载均衡 2、Ribbon实现服务…

大模型企业落地:制造业可以选择的应用场景

前言 在当今制造业快速发展的背景下,设备稳定运行对于企业的发展至关重要。然而,传统的设备维修模式已无法满足现代企业的需求。为此,引入智能化、数字化的设备维修解决方案成为必然趋势。本文将探讨如何利用大模型技术,构建企业…

智慧工厂人员定位系统的影响与前景展望

随着科技的不断发展,智能制造正在迅速崛起,而智慧工厂人员定位系统作为其中的重要组成部分,正在改变传统制造业的面貌。这一系统通过利用物联网、室内定位等技术手段,能够实时准确地追踪和监控工厂内人员的位置。那么,…

数据采集项目2-业务数据同步

全量同步 每天都将业务数据库中的全部数据同步一份到数据仓库 全量同步采用DataX datax datax使用 执行 python /opt/module/datax/bin/datax.py /opt/module/datax/job/job.json 更多job.json配置文件在: 生成的DataX配置文件 java -jar datax-config-genera…

linux C语言 pthread多线程11错误 卡死

pthread新手坑,跟着网上直接写,pthread_create然后就让函数跑,跑完了直接在函数里面return。这个流程,小测试,一点毛病都没有,跑得贼溜。 但是客户拿去压测七天后,出现卡死的现象。分析后&…