Graph Cut

Graph Cut

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

1. Graph Cuts图

        此类方法把图像分割问题与图的最小割(min cut)问题相关联。首先用一个无向图G=<V,E>表示要分割的图像,V和E分别是顶点(vertex)和边(edge)的集合。此处的Graph和普通的Graph稍有不同。普通的图由顶点和边构成,如果边的有方向的,这样的图被则称为有向图,否则为无向图,且边是有权值的,不同的边可以有不同的权值,分别代表不同的物理意义。而Graph Cuts图是在普通图的基础上多了2个顶点,这2个顶点分别用符号”S”和”T”表示,统称为终端顶点。其它所有的顶点都必须和这2个顶点相连形成边集合中的一部分。所以Graph Cuts中有两种顶点,也有两种边。
        第一种顶点和边:第一种普通顶点对应于图像中的每个像素。每两个邻域顶点(对应于图像中每两个邻域像素)的连接就是一条边。这种边也叫n-links。
        第二种顶点和边:除图像像素外,还有另外两个终端顶点,叫S(source:源点,取源头之意)和T(sink:汇点,取汇聚之意)。每个普通顶点和这2个终端顶点之间都有连接,组成第二种边。这种边也叫t-links。
在这里插入图片描述
        上图就是一个图像对应的s-t图,每个像素对应图中的一个相应顶点,另外还有s和t两个顶点。上图有两种边,实线的边表示每两个邻域普通顶点连接的边n-links,虚线的边表示每个普通顶点与s和t连接的边t-links。在前后景分割中,s一般表示前景目标,t一般表示背景。
        图中每条边都有一个非负的权值we,也可以理解为cost(代价或者费用)。一个cut(割)就是图中边集合E的一个子集C,那这个割的cost(表示为|C|)就是边子集C的所有边的权值的总和。
        Graph Cuts中的Cuts是指这样一个边的集合,很显然这些边集合包括了上面2种边,该集合中所有边的断开会导致残留”S”和”T”图的分开,所以就称为“割”。如果一个割,它的边的所有权值之和最小,那么这个就称为最小割,也就是图割的结果。而福特-富克森定理表明,网路的最大流max flow与最小割min cut相等。所以由Boykov和Kolmogorov发明的max-flow/min-cut算法就可以用来获得s-t图的最小割。这个最小割把图的顶点划分为两个不相交的子集S和T,其中s∈S,t∈ T和S∪T=V。这两个子集就对应于图像的前景像素集和背景像素集,那就相当于完成了图像分割。
        也就是说图中边的权值就决定了最后的分割结果,那么这些边的权值怎么确定呢?

2. 最小化能量函数

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

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

(1)区域项:

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

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

(2) 边界项:

        其中,p和q为邻域像素,边界平滑项主要体现分割L的边界属性,B<p,q>可以解析为像素p和q之间不连续的惩罚,一般来说如果p和q越相似(例如它们的灰度),那么B<p,q>越大,如果他们非常不同,那么B<p,q>就接近于0。换句话说,如果两邻域像素差别很小,那么它属于同一个目标或者同一背景的可能性就很大,如果他们的差别很大,那说明这两个像素很有可能处于目标和背景的边缘部分,则被分割开的可能性比较大,所以当两邻域像素差别越大,B<p,q>越小,即能量越小。
        综上:当像素强度倾向于目标像素时,该像素与终端顶点s所连成的边的权值weight要大于终端顶点t与该像素相连形成的边的权值,为了使能量函数更小,即需要割断该点与终端顶点t所连成的边;当相邻像素相似时,B值较大,为了使能量函数尽量小,该处不该被分割,因此保留下来,反之,则可能被分割。

3. min cut

        所构建的图有两类顶点,两类边和两类权值。普通顶点由图像每个像素组成,每两个邻域像素之间存在一条边,它的权值由“边界平滑能量项”来决定。还有两个终端顶点s(目标)和t(背景),每个普通顶点和s都存在连接,也就是边,边的权值由“区域能量项”Rp(0)来决定,每个普通顶点和t连接的边的权值由“区域能量项”Rp(1)来决定。这样所有边的权值就可以确定了,也就是图就确定了。
在这里插入图片描述
         这时候,就可以通过min cut算法来找到最小的割,这个min cut就是权值和最小的边的集合,这些边的断开恰好可以使目标和背景被分割开,也就是min cut对应于能量的最小化。而min cut和图的max flow是等效的,故可以通过max flow算法来找到s-t图的min cut。
         目前的算法主要有:
         (1)Goldberg-Tarjan
         (2) Ford-Fulkerson
         (3)上述两种方法的改进算法

4. 分割示意图

         Graph cut的3x3图像分割示意图:取两个种子点(就是人为的指定分别属于目标和背景的两个像素点),然后建立一个图,,然后找到权值和最小的边的组合,也就是图中的cut,即完成了图像分割的功能。
在这里插入图片描述

5. 图割算法分类

        图割分割方法的发展方向大体分为了3类,分别是提高图割分割速度、交互式图割图像分割和加入先验形状的图割图像分割。

A. speed-up based graph cut
        传统的图割方法,将每个像素作为1个顶点进行计算,这样的计算量较大。然而在很多情况下,目标在图像中只占很小的部分,因此我们可以只对包含目标的部分图像计算,通过对背景的减除,实现降低计算量的目的。除此之外,当图像中相邻像素非常相似的时候,可将这两个像素合并成一个像素运算,因此,这里又引入了聚类算法。在其他思路上,用超像素方法,将每个超像素作为1个像素或者看做图的顶点进行运算,从而可以降低计算量。
B. Interactive-based graph cut
         在图像分割中,很多图像很难实现纯自动分割,因此,引入交互式方法是十分必要的。在部分文献中提到,用户手动设定边界框,边界框中心区域作为前景,通过对前景区域的像素运算可得到前景柱状图,反之,可得到背景柱状图。部分文献中,迭代交互式图割方法得到应用。这种方法将每次迭代后产生结果后,对种子点进行修正,添加更多种子点,直到分割结果满意为止,这种方法对弱边缘图像分割结果理想。
C. 加入先验信息的图割方法

6. 思考总结

        图割是非常好的分割方法,但是计算量大,个人认为减少计算量,自动确定种子点或目标区域是重要的改进方向。

7. 参考资料

[1]《Interactive Graph Cuts for Optimal Boundary & Region Segmentation of Objects in N-D Images》(Boykov,iccv01)
         这篇paper主要讲怎么用graph cut来做image segmentation。在Boykov 和 Kolmogorov 的主页上有大量的code,包括maxflow/min-cut、stereo algorithms等算法:
                  http://pub.ist.ac.at/~vnk/software.html
                  http://vision.csd.uwo.ca/code/

[2] 康奈尔大学的graphcuts研究主页:
                  http://www.cs.cornell.edu/~rdz/graphcuts.html
[3]《Image Segmentation: A Survey of Graph-cut Methods》(Faliu Yi,ICSAI 2012)

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Graphcut是一种图像分割算法,它基于图论理论和最小割最大流算法。在Python中,我们可以使用一些库来实现Graphcut算法,例如OpenCV和scikit-image。 在OpenCV中,我们可以使用grabCut函数来实现图像分割。在使用grabCut函数之前,我们需要准备一个掩膜图像,用于指示算法应该将图像的哪一部分视为背景和前景。掩膜图像通常是一个与原始图像尺寸相同的二进制图像,其中前景区域用白色表示,背景区域用黑色表示。 以下是一个使用OpenCV的grabCut函数的简单例子: ``` python import cv2 import numpy as np # 读取图像 img = cv2.imread('image.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, 300, 500) # 运行grabCut算法 cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT) # 通过掩膜图像提取前景区域 mask2 = np.where((mask==2)|(mask==0), 0, 1).astype('uint8') img = img * mask2[:, :, np.newaxis] # 显示结果 cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 另一个库scikit-image也提供了Graphcut的实现。在scikit-image中,我们可以使用函数`graph.cut_normalized`来实现图像分割。该函数需要构建一个图形数据结构,其中每个像素作为图的一个节点,通过定义节点之间的边来表示像素之间的相似性。然后运行图割算法,将图像分割为前景和背景。 以下是一个使用scikit-image的Graphcut算法的简单例子: ``` python import numpy as np from skimage.feature import graph from skimage.segmentation import cut_normalized from skimage.io import imread # 读取图像 img = imread('image.jpg') # 转换图像为灰度图 gray_img = np.mean(img, axis=2).astype('uint8') # 构建图形数据结构 g = graph.rag_mean_color(gray_img, img) # 运行图割算法 labels = cut_normalized(gray_img, g) # 对每个像素进行着色 out = img.copy() for i in np.unique(labels): out[labels == i] = np.mean(img[labels == i], axis=0) # 显示结果 plt.imshow(out) plt.axis('off') plt.show() ``` 上述例子中,我们首先将图像转换为灰度图,然后构建一个连通图,其中每个节点表示一个像素,边的权重表示像素之间的相似性。接下来,我们运行图割算法,并根据分割结果对每个像素进行着色,最后显示结果。 以上是使用Python实现Graphcut算法的简单示例。根据具体的应用场景和需求,我们可以进一步调整参数和优化算法来获得更好的分割效果。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值