图像分割之(二)Graph Cut(图割)

article/2025/10/26 5:55:51

图像分割之(二)Graph Cut(图割)

zouxy09@qq.com

http://blog.csdn.net/zouxy09

 

       上一文对主要的分割方法做了一个概述。那下面我们对其中几个比较感兴趣的算法做个学习。下面主要是Graph Cut,下一个博文我们再学习下Grab Cut,两者都是基于图论的分割方法。另外OpenCV实现了Grab Cut,具体的源码解读见博文更新。接触时间有限,若有错误,还望各位前辈指正,谢谢。

       Graph cuts是一种十分有用和流行的能量优化算法,在计算机视觉领域普遍应用于前背景分割(Image segmentation)、立体视觉(stereo vision)、抠图(Image matting)等。

       此类方法把图像分割问题与图的最小割(min cut)问题相关联。首先用一个无向图G=<VE>表示要分割的图像,VE分别是顶点(vertex)和边(edge)的集合。此处的Graph和普通的Graph稍有不同。普通的图由顶点和边构成,如果边的有方向的,这样的图被则称为有向图,否则为无向图,且边是有权值的,不同的边可以有不同的权值,分别代表不同的物理意义。而Graph Cuts图是在普通图的基础上多了2个顶点,这2个顶点分别用符号”S”和”T”表示,统称为终端顶点。其它所有的顶点都必须和这2个顶点相连形成边集合中的一部分。所以Graph Cuts中有两种顶点,也有两种边。

第一种顶点和边是:第一种普通顶点对应于图像中的每个像素。每两个邻域顶点(对应于图像中每两个邻域像素)的连接就是一条边。这种边也叫n-links

第二种顶点和边是:除图像像素外,还有另外两个终端顶点,叫Ssource:源点,取源头之意)和Tsink:汇点,取汇聚之意)。每个普通顶点和这2个终端顶点之间都有连接,组成第二种边。这种边也叫t-links

       上图就是一个图像对应的s-t图,每个像素对应图中的一个相应顶点,另外还有st两个顶点。上图有两种边,实线的边表示每两个邻域普通顶点连接的边n-links,虚线的边表示每个普通顶点与st连接的边t-links。在前后景分割中,s一般表示前景目标,t一般表示背景。

       图中每条边都有一个非负的权值we,也可以理解为cost(代价或者费用)。一个cut(割)就是图中边集合E的一个子集C,那这个割的cost(表示为|C|)就是边子集C的所有边的权值的总和。

         Graph Cuts中的Cuts是指这样一个边的集合,很显然这些边集合包括了上面2种边,该集合中所有边的断开会导致残留”S”和”T”图的分开,所以就称为“割”。如果一个割,它的边的所有权值之和最小,那么这个就称为最小割,也就是图割的结果。而福特-富克森定理表明,网路的最大流max flow与最小割min cut相等。所以由BoykovKolmogorov发明的max-flow/min-cut算法就可以用来获得s-t图的最小割。这个最小割把图的顶点划分为两个不相交的子集ST,其中s St TST=V 。这两个子集就对应于图像的前景像素集和背景像素集,那就相当于完成了图像分割。

        也就是说图中边的权值就决定了最后的分割结果,那么这些边的权值怎么确定呢?

       图像分割可以看成pixel labeling(像素标记)问题,目标(s-node)的label设为1,背景(t-node)的label设为0,这个过程可以通过最小化图割来最小化能量函数得到。那很明显,发生在目标和背景的边界处的cut就是我们想要的(相当于把图像中背景和目标连接的地方割开,那就相当于把其分割了)。同时,这时候能量也应该是最小的。假设整幅图像的标签label(每个像素的label)为L= {l1,l2,,,, lp },其中li0(背景)或者1(目标)。那假设图像的分割为L时,图像的能量可以表示为:

E(L)=aR(L)+B(L)

       其中,R(L)为区域项(regional term),B(L)为边界项(boundary term),而a就是区域项和边界项之间的重要因子,决定它们对能量的影响大小。如果a0,那么就只考虑边界因素,不考虑区域因素。E(L)表示的是权值,即损失函数,也叫能量函数,图割的目标就是优化能量函数使其值达到最小。

区域项:

,其中Rp(lp)表示为像素p分配标签lp的惩罚,Rp(lp)能量项的权值可以通过比较像素p的灰度和给定的目标和前景的灰度直方图来获得,换句话说就是像素p属于标签lp的概率,我希望像素p分配为其概率最大的标签lp,这时候我们希望能量最小,所以一般取概率的负对数值,故t-link的权值如下:

Rp(1) = -ln Pr(Ip|’obj’) Rp(0) = -ln Pr(Ip|’bkg’)

        由上面两个公式可以看到,当像素p的灰度值属于目标的概率Pr(Ip|’obj’)大于背景Pr(Ip|’bkg’),那么Rp(1)就小于Rp(0),也就是说当像素p更有可能属于目标时,将p归类为目标就会使能量R(L)小。那么,如果全部的像素都被正确划分为目标或者背景,那么这时候能量就是最小的。

边界项:

        其中,pq为邻域像素,边界平滑项主要体现分割L的边界属性,B<p,q>可以解析为像素pq之间不连续的惩罚,一般来说如果pq越相似(例如它们的灰度),那么B<p,q>越大,如果他们非常不同,那么B<p,q>就接近于0。换句话说,如果两邻域像素差别很小,那么它属于同一个目标或者同一背景的可能性就很大,如果他们的差别很大,那说明这两个像素很有可能处于目标和背景的边缘部分,则被分割开的可能性比较大,所以当两邻域像素差别越大,B<p,q>越小,即能量越小。

        好了,现在我们来总结一下:我们目标是将一幅图像分为目标和背景两个不相交的部分,我们运用图分割技术来实现。首先,图由顶点和边来组成,边有权值。那我们需要构建一个图,这个图有两类顶点,两类边和两类权值。普通顶点由图像每个像素组成,然后每两个邻域像素之间存在一条边,它的权值由上面说的“边界平滑能量项”来决定。还有两个终端顶点s(目标)和t(背景),每个普通顶点和s都存在连接,也就是边,边的权值由“区域能量项”Rp(1)来决定,每个普通顶点和t连接的边的权值由“区域能量项”Rp(0)来决定。这样所有边的权值就可以确定了,也就是图就确定了。这时候,就可以通过min cut算法来找到最小的割,这个min cut就是权值和最小的边的集合,这些边的断开恰好可以使目标和背景被分割开,也就是min cut对应于能量的最小化。而min cut和图的max flow是等效的,故可以通过max flow算法来找到s-t图的min cut。目前的算法主要有:

1) Goldberg-Tarjan

2) Ford-Fulkerson

3) 上诉两种方法的改进算法

 

权值:

         Graph cut3x3图像分割示意图:我们取两个种子点(就是人为的指定分别属于目标和背景的两个像素点),然后我们建立一个图,图中边的粗细表示对应权值的大小,然后找到权值和最小的边的组合,也就是(c)中的cut,即完成了图像分割的功能。

上面具体的细节请参考:

Interactive Graph Cuts for Optimal Boundary & Region Segmentation of Objects in N-D Images》(Boykoviccv01)这篇paper讲怎么用graphcut来做image segmentation

Boykov Kolmogorov 俩人的主页上就有大量的code。包括maxflow/min-cutstereo algorithms等算法:

http://pub.ist.ac.at/~vnk/software.html

http://vision.csd.uwo.ca/code/

康奈尔大学的graphcuts研究主页也有不少信息:

http://www.cs.cornell.edu/~rdz/graphcuts.html

Image Segmentation: A Survey of Graph-cut Methods》(Faliu YiICSAI 2012

 


http://chatgpt.dhexx.cn/article/EBDrjFl0.shtml

相关文章

【前端必学】PS切图详细教程3种方法(图层切图,切片,切图神器cutterman)

PSD图像格式是Photoshop的专用格式&#xff0c;里面可以存放图层、通道、遮置等多种设计稿&#xff0c;对我们前端人员来说&#xff0c;最大的优点&#xff0c;我们可以直接从上面复制文字&#xff0c;获得图片&#xff0c;还可以测量大小和距离&#xff0c;我们开发需要的是一…

vue中的.passive修饰符的作用以及应用场景

passive这个修饰符会执行默认方法。你们可能会问&#xff0c;明明默认执行为什么会设置这样一个修饰符。这就要说一下这个修饰符的本意了。 浏览器只有等内核线程执行到事件监听器对应的JavaScript代码时&#xff0c;才能知道内部是否会调用preventDefault函数来阻止事件的默认…

burp插件系列1 passive-scan-client

阅读目录 插件介绍插件使用 插件介绍 被动扫描流量转发插件 项目地址&#xff1a; https://github.com/c0ny1/passive-scan-client这个项目其实主要功能和目前版本burp的Upstream Proxy Server功能基本重复&#xff0c;但是其也有自己的优势 不用每次新打开burp都要去配置U…

vue中的事件修饰符.self、.capture和.passive

vue中的事件修饰符有6种&#xff1a; .stop.prevent.capture.once.self.passive .stop是stopPropagation停止冒泡&#xff0c; .prevent是preventDefault阻止默认事件&#xff0c; .once是点击事件将只会触发一次 <!-- 点击事件将只会触发一次 --> <a v-on:click.o…

FileZilla客户端连接腾讯云FTP服务器时出现“227 Entering Passive Mode”

FTP的主动模式(PORT Mode)及被动模式(Passive Mode) FTP的特殊性&#xff1a; 大多数的TCP服务是使用单个的连接&#xff0c;一般是客户向服务器的一个周知端口发起连接&#xff0c;然后使用这个连接进行通讯。但是&#xff0c;FTP协议却有所不同&#xff0c;它使用双向的多个连…

FTP Entering Extended Passive Mode

目录 原因 两种方法解决,哪个行用哪种 方法一 方法二 原因 FTP的连接建立有两种模式PORT

ftp的passive模式

昨天调试了半天的ftp passive模式&#xff0c;记录一下 今天在一台测试服务器上搭建ftp&#xff0c;折腾了许久。 主要是不了解ftp的passive模式和port模式的区别。这里记录一下。 和passive模式对应的叫做port模式&#xff0c;也叫做standard模式&#xff0c;也叫主动模式。 每…

一篇文章彻底掌握 FTP 服务器的 ACTIVE 与 PASSIVE 工作模式

1 背景 某客户现场&#xff0c;每天都会批量生成大量 CSV 文件存放到 FTP 系统&#xff0c;这些 CSV 文件需要导入到大数据平台 HIVE 数仓中做后续离线分析&#xff0c;且 HIVE 数仓中的离线分析作业目前是使用 JENKINS 来调度的。 由于这些 CSV 文件是每天都会生成&#xff0c…

passive 的事件监听器

很久以前&#xff0c;addEventListener() 的参数约定是这样的&#xff1a; addEventListener(type, listener, useCapture) 后来&#xff0c;最后一个参数&#xff0c;也就是控制监听器是在捕获阶段执行还是在冒泡阶段执行的 useCapture 参数&#xff0c;变成了可选参数&…

强化学习之Passive learning求解 (1)

在MDP系列博客中&#xff0c;我们以一个Agent在4*3网格中寻找终点最优的路径策略为例&#xff0c;论述了MDP问题的原理和求解。有了MDP讲解作为基础之后&#xff0c;我们就可以正式的切入到“强化学习”的学习中来了。强化学习的目的是通过观测到的reward来为当前环境学习一个&…

【重要!!】passive优化页面性能

在js中给dom元素添加监听事件&#xff1a; let dom1document.getElementById("box1"); function box(that){console.log(that); } dom1.addEventListener("click",function(){box(1)});一般都是这样&#xff0c;但是还是有第三个参数&#xff0c;Boolean类…

Passive Event Listener

起源 最近打开项目随便点点&#xff0c;控制台就开始报警&#xff1a; Added non-passive event listener to a scroll-blocking ‘mousewheel’ event. Consider marking event handler as ‘passive’ to make the page more responsive 可以看到警告信息是element-ui和echa…

passive的作用和原理

passived到底有什么用&#xff1f; passived主要用于优化浏览器页面滚动的性能&#xff0c;让页面滚动更顺滑~~BetterScroll&#xff1a;可能是目前最好用的移动端滚动插件 passived产生的历史时间线 addEventListener()&#xff1a;大家都是认识的&#xff0c;为dom添加触发…

Java并发编程—CompletableFuture的介绍和使用

在博主上一篇博客介绍中&#xff0c;Java并发编程—java异步Future的迭代过程_小魏快起床的博客-CSDN博客&#xff0c;这里面给大家分析了Future的使用过程和一些存在的问题&#xff0c;那么针对里面出现的阻塞问题&#xff0c;博主将在这一篇文章给大家介绍清楚 &#x1f34f…

Java8 CompletableFuture runAsync等使用学习总结 submit() execute()等

一般的 Executors 的 execute以及submit 并发包下 Executors 创建的线程存在 一个 execute()&#xff0c;以及三个 submit() 不同的是使用 execute() 执行的任务是没有返回值的&#xff0c;使用 submit() 则是存在返回值的&#xff0c;这与接下里要说的 CompletableFuture.run…

实现异步编程,这个工具类你得掌握!

前言 最近看公司代码&#xff0c;多线程编程用的比较多&#xff0c;其中有对CompletableFuture的使用&#xff0c;所以想写篇文章总结下 在日常的Java8项目开发中&#xff0c;CompletableFuture是很强大的并行开发工具&#xff0c;其语法贴近java8的语法风格&#xff0c;与st…

Java异步编程之CompletableFuture

异步任务 Future获取异步任务结果 利用 Java 并发包提供的 Future 可以很容易获得异步任务的执行结果&#xff0c;无论异步任务是通过线程池 ThreadPoolExecutor 执行的&#xff0c;还是通过手工创建子线程来执行的。利用多线程可以快速将一些串行的任务并行化&#xff0c;从而…

JUC异步编程

什么是JUC JUC的意思是java并发编程工具包&#xff0c;是java.util.concurrent包的简称。目的就是为了更好的支持高并发任务&#xff0c;让开发者利用这个包进行的多线程开发时&#xff0c;可以有效的减少竞争条件和死锁线程。 异步编程 模拟用户下单操作。。。 1、根据地址…

线程、多线程的使用、线程池、异步(CompletableFuture)-48

一&#xff1a;线程 1.初始化线程的四种方式 1&#xff09;、继承 Thread public class ThreadTest {public static void main(String[] args) {System.out.println("main...start...");Thread01 thread new Thread01();//启动线程thread.start();System.out.pri…

CompletableFuture 执行异步任务

CompletableFuture 执行异步任务 参考&#xff1a; (10条消息) Java 8 的异步编程利器 CompletableFuture 真香&#xff01;_不才陈某的博客-CSDN博客 提供几十种方法&#xff0c;帮助异步任务执行调用&#xff1b; 主要包括&#xff1a; 创建异步任务任务异步回调多个任务…