opencv - py_imgproc - py_grabcut GrabCut 算法提取前景

news2024/11/7 7:35:17

文章目录

  • 使用 GrabCut 算法进行交互式前景提取
    • 目标
    • 理论
    • 演示

使用 GrabCut 算法进行交互式前景提取

目标

在本章中

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

理论

GrabCut 算法由英国剑桥微软研究院的 Carsten Rother、Vladimir Kolmogorov 和 Andrew Blake 设计。在他们的论文 “GrabCut”:使用迭代图切割进行交互式前景提取 中。需要一种以最少的用户交互进行前景提取的算法,结果就是 GrabCut。

从用户的角度来看它是如何工作的?首先,用户在前景区域周围绘制一个矩形(前景区域应完全在矩形内)。然后算法迭代地对其进行分割以获得最佳结果。完成。但在某些情况下,分割效果并不好,例如,它可能将某些前景区域标记为背景,反之亦然。在这种情况下,用户需要进行精细的修饰。只需在存在错误结果的图像上进行一些描边即可。描边基本上表示“嘿,这个区域应该是前景,你将其标记为背景,在下一次迭代中对其进行更正”*或将其相反标记为背景。然后在下一次迭代中,您会得到更好的结果。

参见下图。第一个球员和足球被包裹在一个蓝色矩形中。然后用白色描边(表示前景)和黑色描边(表示背景)进行一些最后的修饰。我们得到了一个不错的结果。

在这里插入图片描述

那么背景会发生什么?

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

如下图所示(图片来源:http://www.cs.ru.ac.za/research/g02m1682/)

在这里插入图片描述

演示

现在我们使用 OpenCV 进行 grabcut 算法。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)
  • bdgModelfgdModel - 这些是算法内部使用的数组。您只需创建两个大小为 (1,65) 的 np.float64 类型零数组。
  • iterCount - 算法应运行的迭代次数。
  • mode - 它应该是 cv.GC_INIT_WITH_RECTcv.GC_INIT_WITH_MASK 或两者结合
    决定我们绘制的是矩形还是最终的修饰笔触。

首先让我们看看矩形模式。我们加载图像,创建一个类似的遮罩图像。我们创建 fgdModelbgdModel。我们给出矩形参数。这一切都很简单。让算法运行 5 次迭代。模式应该是cv.GC_INIT_WITH_RECT,因为我们使用的是矩形。然后运行 ​​grabcut。它会修改遮罩图像。在新的遮罩图像中,像素将用四个标志标记,表示如上所述的背景/前景。因此,我们修改了掩码,将所有 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()

请参阅以下结果:

在这里插入图片描述

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

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

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

相关文章

视频制作软件新手必备:8款剪辑工具剪辑思路分享!

随着视频的高度发展,视频已成为一种重要的工具,用以学习娱乐、记录生活点滴以及传递各类信息。不论是制作个人MV、进行企业宣传,还是创作短视频内容,拥有一款功能恰当的视频剪辑软件都显得至关重要。对于初学者而言,选…

无人机避障——路径规划篇(一) JPS跳点搜索算法A*算法对比

JSP 跳点搜索算法与改进 A*算法对比 一、算法概述: 跳点搜索(Jump Point Search,JPS)算法:一种用于路径规划的启发式搜索算法。它主要用于在网格地图(如游戏地图、机器人运动规划地图等)中快速找到从起点到终点的最短路径。该算法在改进 A*算法的基础上进行了优化,通过跳过一…

解决Linux安装Anaconda后出现的conda: command not found问题

参考链接:解决Linux安装Anaconda后出现的conda: command not found问题-百度开发者中心

AI直播带货场景切换模块的搭建!

AI直播带货,作为电商领域的新宠,正以其独特的魅力和高效的营销手段,引领着销售模式的新变革。 在AI直播带货中,场景切换模块是不可或缺的一部分,它不仅能够提升观众的观看体验,还能更好地展示商品&#xf…

15 Docker容器存储架构:docker存储驱动简介

文章目录 一、Docker 存储驱动探索1.1 存储驱动1.2 存储驱动方式1.3 非持久化存储1.4 持久化存储一、Docker 存储驱动探索 1.1 存储驱动 Storage driver处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户提供了多层数据合并后的统一视图。 [superman@docker ~]$…

Aicbo:一键生成高质量画作,适合初学者的AI绘画助手

越来越多的智能工具开始进入人们的视野,它们不仅简化了创作流程,还极大地提高了作品的质量。在这一背景下,Aicbo作为一款新兴的AI绘画工具,以其独特的优势和免费试用的政策,迅速获得了广泛的关注和好评。本文将从多个角…

STM32 从0开始系统学习5

目录 STM32 GPIO输入的四种模式 Practice And Usage 练习与封装 Detailed And Reference 更加具体的说明 输入浮空模式 输入上拉模式 输入下拉模式 模拟功能 我们下面聊一聊输入的事情,输入指的是我们的处理器从外部端口接受外设发过来的信号。在我们没有接…

使用Git进行版本控制的最佳实践

文章目录 Git简介基本概念仓库(Repository)提交(Commit)分支(Branching) 常用命令初始化仓库添加文件提交修改查看状态克隆仓库分支操作合并分支推送更改 最佳实践使用有意义的提交信息定期推送至远程仓库使…

冒泡排序和二分查找--go

冒泡排序的逻辑 二分查找的逻辑 func bubbleSort(arr *[5]int){//冒泡排序fmt.Println(*arr)temp : 0for j : len(*arr); j > 0; j-- {for i : 0; i < j-1; i {temp (*arr)[i]if((*arr)[i] > (*arr)[i1]){(*arr)[i] (*arr)[i1](*arr)[i1] temp}}} }func binaryF…

flutter区别于vue的写法

View.dart 页面渲染&#xff1a; 类似于vue里面使用 <template> <div> <span> <textarea>等标签绘制页面, flutter 里面则是使用不同的控件来绘制页面 样式 与传统vue不同的是 flutter里面没有css/scss样式表&#xff0c; Flutter的理念是万物皆…

电影《焚城》全国上映 王丹妮诠释新时代女性力量

今日&#xff0c;电影《焚城》全国上映&#xff0c;该片由刘德华、白宇、莫文蔚和王丹妮主演&#xff0c;以一场由高强度放射性物质铯137泄漏引发的城市灾难为背景&#xff0c;深刻描绘了人们在生死存亡关头的抉择与抗争。 王丹妮在片中饰演飒爽独立、智慧勇敢的消防队长Madam …

uniapp:启动界面关闭时长控制

代码控制关闭启动界面 App启动后不会自动关闭启动界面&#xff0c;需要在代码中调用plus.navigator.closeSplashscreen关闭启动界面。"app-plus" : {"splashscreen" : {"alwaysShowBeforeRender" : false,"autoclose" : false,}, }很多…

Three.js 快速入门构建你的第一个 3D 应用

![ 开发领域&#xff1a;前端开发 | AI 应用 | Web3D | 元宇宙 技术栈&#xff1a;JavaScript、React、Three.js、WebGL、Go 经验经验&#xff1a;6年 前端开发经验&#xff0c;专注于图形渲染和AI技术 开源项目&#xff1a;github 晓智元宇宙、数字孪生引擎、前端面试题 大家好…

二:java 基础知识(2)-- 初始java/语法基础

目录 idea中文插件 第一个 Java 程序 Java数据类型&#xff0c;常量与变量 1. 数据类型 1.1 基本数据类型 1.2 引用数据类型 2. 常量 2.1 特性 2.2 定义常量 ​编辑 3. 变量 3.1 变量的定义与初始化 3.2 变量的类型 局部变量&#xff1a;在方法内声明的变量&#xff0…

【AAOS】【源码分析】CarSystemUI -- CarSystemBar

CarSystemBar不像Android手机那样固定的顶部“状态栏”和底部“导航栏”,而是将StatusBar和NavigationBar都统称为SystemBar,可以通过如下配置为每侧最多配置一个“系统栏”。 packages/apps/Car/SystemUI/res/values/config.xml<!-- Configure which system bars should …

企业物流管理数据仓库建设的全面指南

文章目录 一、物流管理目标二、总体要求三、数据分层和数据构成&#xff08;1&#xff09;数据分层&#xff08;2&#xff09;数据构成 四、数据存储五、数据建模和数据模型&#xff08;1&#xff09;数据建模&#xff08;2&#xff09;数据模型 六、总结 在企业物流管理中&…

多线程学习篇六:park / unpark

1. API LockSupport.park()&#xff1a;暂停当前线程LockSupport.unpark (线程对象)&#xff1a;恢复某个线程的运行 1.1 先 park 再 unpark main 线程睡眠时间大于 t1 线程睡眠时间 Slf4j(topic "c.Test01") public class Test01 {public static void main(Str…

计算机网络:网络层 —— IPv4 数据报的首部格式

文章目录 IPv4数据报的首部格式IPv4数据报分片生存时间 TTL字段协议字段首部检验和字段 IPv4数据报的首部格式 IPv4 数据报的首部格式及其内容是实现 IPv4 协议各种功能的基础。 在 TCP/IP 标准中&#xff0c;各种数据格式常常以32比特(即4字节)为单位来描述 固定部分&#x…

基于SSM演出道具租赁系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;商家管理&#xff0c;道具类型管理&#xff0c;道具出租管理&#xff0c;租赁订单管理&#xff0c;道具归还管理&#xff0c;系统管理 商家账号功能包括&#xff1a;系统首页&…

《使用Gin框架构建分布式应用》阅读笔记:p272-p306

《用Gin框架构建分布式应用》学习第15天&#xff0c;p272-p306总结&#xff0c;总35页。 一、技术总结 1.TDD(test-driven development) 虽然经常看到TDD这个属于&#xff0c;从本人的工作经历看&#xff0c;实际开发中用得相对较少。 2.unitest(单元测试) go语言开发中&a…