当前位置: 首页 > news >正文

【OpenCV】基于GrabCut算法的交互式前景提取

介绍

GrabCut 算法是一种用于图像分割的交互式前景提取技术,它结合了图割(Graph Cut)方法和迭代优化过程。该算法最初由 Rother, Kolmogorov 和 Blake 在 2004 年提出,并因其高效性和准确性而被广泛应用于计算机视觉领域。OpenCV 提供了 cv2.grabCut() 函数来实现这一算法,使得开发者可以方便地在应用程序中使用。

GrabCut 算法的基本原理

  1. 初始化:用户通过绘制矩形或自由手绘的方式标记出大致的前景区域(即对象所在的位置),同时还可以选择性地标记背景区域。
  2. 构建图形模型:基于用户的输入,算法会为每个像素创建一个节点,并且在相邻像素之间建立边。这些边的权重反映了像素间的相似度,通常基于颜色信息。
  3. 概率分布估计:对于已知的前景和背景区域,分别拟合高斯混合模型(GMMs, Gaussian Mixture Models),用以描述其颜色分布特性。
  4. 能量函数最小化:定义一个能量函数,其中包含数据项(反映像素与各自GMM之间的匹配程度)和平滑项(鼓励相邻像素具有相同的标签)。然后利用图割算法找到使能量函数最小化的解决方案。
  5. 迭代改进:根据前一次迭代的结果更新GMM参数,并重复上述步骤直至收敛或达到预定次数。

 

理论

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

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

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

grabcut_output1.jpg

那背景会发生什么?

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

如下图所示(图片提供: "GrabCut" )

grabcut_scheme.jpg

演示

现在我们使用 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**或合并后决定我们是否正在绘图矩形或最终修饰笔画。

        首先让我们看看矩形模式。我们加载图像,创建一个类似的蒙版图像。我们创建 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()

结果如下:

grabcut_rect.jpg

        我们将用 1 像素(确定的前景)给出一个精细的修饰。与此同时,有些地方已经出现了我们不想要的图片,还有一些标识。我们需要删除它们。在那里我们提供一些 0 像素的修饰(确定背景)。因此,我们如前所述地调整了结果掩膜。

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


newmask = cv.imread('newmask.png',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()

看下面的结果:

grabcut_mask.jpg

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

相关文章:

【OpenCV】基于GrabCut算法的交互式前景提取

介绍 GrabCut 算法是一种用于图像分割的交互式前景提取技术,它结合了图割(Graph Cut)方法和迭代优化过程。该算法最初由 Rother, Kolmogorov 和 Blake 在 2004 年提出,并因其高效性和准确性而被广泛应用于计算机视觉领域。OpenCV…...

【Flask+OpenAI】利用Flask+OpenAI Key实现GPT4-智能AI对话接口demo - 从0到1手把手全教程(附源码)

文章目录 前言环境准备安装必要的库 生成OpenAI API代码实现详解导入必要的模块创建Flask应用实例配置OpenAI API完整代码如下(demo源码)代码解析 利用Postman调用接口 了解更多AI内容结尾 前言 Flask作为一个轻量级的Python Web框架,凭借其…...

最短路----Dijkstra算法详解

简介 迪杰斯特拉(Dijkstra)算法是一种用于在加权图中找到单个源点到所有其他顶点的最短路径的算法。它是由荷兰计算机科学家艾兹格迪科斯彻(Edsger Dijkstra)在1956年提出的。Dijkstra算法适用于处理带有非负权重的图。迪杰斯特拉…...

ORB-SLAM3源码学习:G2oTypes.cc: void EdgeInertial::computeError 计算预积分残差

前言 这部分函数涉及了g2o的内容以及IMU相关的推导内容,需要你先去进行这部分的学习。 1.函数声明 void EdgeInertial::computeError() 2.函数定义 涉及到的IMU的公式: {// TODO Maybe Reintegrate inertial measurments when difference between …...

Unity协程机制详解

Unity的协程(Coroutine)是一种异步编程的机制,允许在多个帧之间分割代码的执行,而不阻塞主线程。与传统的多线程不同,Unity的协程在主线程中运行,并不会开启新的线程。 什么是协程? 协程是一种…...

2024年【高压电工】最新解析及高压电工考试总结

高压电工考试是电力行业从业人员必须通过的资格考试之一,它不仅检验了考生对高压电技术的掌握程度,还考验了考生在实际操作中的安全意识和应急处理能力。为了帮助广大考生更好地备考,本文整理了10道2024年高压电工考试的最新解析及总结试题&a…...

OELOVE 6.0城市列表模板

研究了好久OELOVE6.0源码,一直想将城市列表给单独整出来,做地区排名,但是PHP程序都是加密的,非常难搞,做二开都是要命的处理不了,在这里有一个简单方法可以处理城市列表,并且可以自定义TDK&…...

如何将你的 Ruby 应用程序从 OpenSearch 迁移到 Elasticsearch

作者:来自 Elastic Fernando Briano 将 Ruby 代码库从 OpenSearch 客户端迁移到 Elasticsearch 客户端的指南。 OpenSearch Ruby 客户端是从 7.x 版 Elasticsearch Ruby 客户端分叉而来的,因此代码库相对相似。这意味着当将 Ruby 代码库从 OpenSearch 迁…...

day1数据结构,关键字,内存空间存储与动态分区,释放

小练习 在堆区空间连续申请5个int类型大小空间,用来存放从终端输入的5个学生成绩,然后显示5个学生成绩,再将学生成绩升序排序,排序后,再次显示学生成绩。显示和排序分别用函数完成(两种排序方法&#xff0…...

1_linux系统网络性能如何优化——几种开源网络协议栈比较

之前合集《计算机网络从入门到放弃》第一阶段算是已经完成了。都是理论,没有实操,让“程序猿”很难受,操作性不如 Modbus发送的报文何时等到应答和 tcp通信测试报告单1——connect和send。开始是想看linux内核网络协议栈的源码,然…...

【问题记录】07 MAC电脑,使用FileZilla(SFTP)连接堡垒机不成功

项目场景: 使用MAC电脑,以子账号(非root)的形式登录,连接堡垒机CLB(传统型负载均衡),使用FileZilla(SFTP)进行FTP文件传输。 问题描述: MAC电脑…...

前端报错npm ERR cb() never called问题

环境使用node版本v14.21.3&#xff0c;npm版本6.14.18 1.问题描述 1.1使用npm install后报错 npm ERR! cb() never called!npm ERR! This is an error with npm itself. Please report this error at: npm ERR! ? ? <https://npm.community>npm ERR! A complete log…...

康谋方案 | 多源相机数据采集与算法集成测试方案

目录 一、相机组成 二、多源相机采集与测试方案 三、应用案例分享 四、结语 在智能化技术快速发展当下&#xff0c;图像数据的采集与处理逐渐成为自动驾驶、工业等领域的一项关键技术。高质量的图像数据采集与算法集成测试都是确保系统性能和可靠性的关键。随着技术的不断进…...

Graspness 端到端抓取点估计 | 环境搭建 | 模型推理测试

在复杂场景中实现抓取检测&#xff0c;Graspness是一种端到端的方法&#xff1b; 输入点云数据&#xff0c;输出抓取角度、抓取深度、夹具宽度等信息。 开源地址&#xff1a;https://github.com/rhett-chen/graspness_implementation?tabreadme-ov-file 论文地址&#xff1…...

交换机是如何避免数据碰撞的(详细解释 + 示例)

交换机是如何避免数据碰撞的&#xff08;详细解释 示例&#xff09; 1. 独立冲突域 交换机的每个端口都形成一个独立的冲突域。这意味着通过交换机连接的每个设备都拥有自己的通信通道&#xff0c;互不干扰。 示例&#xff1a; 假设一个交换机有4个端口&#xff0c;分别连接…...

魅族手机刷官方系统

从魅族官网下载固件 https://flyme.cn/firmware.html 找到自己的型号&#xff0c;里面有历史版本、最新版&#xff0c;按照需求下载。 下载的是update.zip&#xff0c;改名就不能升级了 方法1 直接点击下载的update.zip包就可以升级。 方法2 将文件移动到文件管理的根目录&a…...

女人想要的,是那份懂她的情绪价值

女人想要的&#xff0c;是那份懂她的情绪价值 在情感的世界里&#xff0c;我们常常听到这样的声音&#xff1a;“我不需要你帮我解决问题&#xff0c;我只希望你能懂我。”这句话&#xff0c;简单却深刻&#xff0c;它揭示了女性在情感需求上的一个独特面向——她们渴望的&…...

[python SQLAlchemy数据库操作入门]-10.性能优化:提升 SQLAlchemy 在股票数据处理中的速度

哈喽,大家好,我是木头左! 当处理大量数据时,如股票数据,默认的ORM操作可能会显得效率低下。本文将探讨如何通过一些技巧和策略来优化SQLAlchemy ORM的性能,从而提升其在股票数据处理中的速度。 1. 选择合适的数据类型 在定义模型时,选择合适的数据类型对于性能至关重要…...

【网络取证篇】取证实战之PHP服务器镜像网站重构及绕密分析

【网络取证篇】取证实战之PHP服务器镜像网站重构及绕密分析 在裸聊敲诈、虚假理财诈骗案件类型中&#xff0c;犯罪分子为了能实现更低成本、更快部署应用的目的&#xff0c;其服务器架构多为常见的初始化网站架构&#xff0c;也称为站库同体服务器&#xff01;也就是说网站应用…...

[python]使用 Pandas 处理 Excel 数据:分割与展开列操作

在数据处理的过程中&#xff0c;时常需要对 Excel 表格中的数据进行清洗与转换&#xff0c;下面介绍使用 Python 中的 Pandas 库对 Excel 文件中的数据进行操作&#xff0c;具体包括分割列、展开数据、清除空格以及格式转换等操作。 目标&#xff1a; 读取一个没有表头的 Exc…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...