本篇主要介绍matlab实现Max-flow/min-cut的方法,介绍一种只实现了Max-flow/min-cut的工具箱Bk_matlab。
一:最大流最小割的由来
了解这个问题之前先说说这个问题的由来吧。最大流最小割最开始从图论的相关概念中引用过来,讲述一个带有起点与终点并且具有边权值的网络图中,如何进行边的切割,把这个网络图分成独立的两个部分(或者多个部分),使得这个切割中被切割的边的权值之和最小。比如现在有一个网络图如下:
那么要把这个图分割成两部分,如上的虚线就是一种切割方式,这个时候可以看到这种切割下消耗的边的权值为3+4=7吧,当然,切割的方式很多种,不同的切割方式自然对应不同的切割边权值,而最大流最小割就是找到一种切割方式使得切割的边的权值之和最小。
这么一看似乎也看不出它的实际意义所在,最大流最小割应该说是应用还挺好的,一个重要应用就在于对图像的分割上面。
先了解一下图像的分割,随便对于一副图像,很容易把图像分成若*分的,常见的图像分割算法有Kmeans,FCM,马尔科夫,等等很多。我们知道,图像简单来说就是矩阵,对于只是灰度图像,那么就是一般的二维矩阵,矩阵中值的大小就是该点的灰度值,那么图像分割问题就是寻找到图像的边界,而边界肯定在两个像素值差别很大的邻域间,如果把两个邻域间的像素值差定义为该邻域的边权值的话,分割问题就转化为如何切割这些边的问题了,这样模型就和上述的对应上了,有点,有边,有边的权值,那么就可以运用上述理论解决图的分割问题了。
在形象一点如下所示:
那么这就是一个对图像的分割。
理论介绍的不够好,贴一些其他关于最大流最小割的介绍性文章:
http://wenku.baidu.com/view/54323c030722192e4536f64f.html?re=view
http://blog.sina.com.cn/s/blog_638502960100g39x.html
最大流/最小割算法总结二:关于图割理论
在正式使用之前先介绍下关于图割理论用来分割图像的方法。还是先贴些比较好的别人写的文章:
图像分割之(二)Graph Cut(图割)
这里面理论化介绍的都是直观上的对图像的操作,而在实际变成实现的时候是要事先转化到一维或者直接调用相应的函数才能对二维的图像进行操作。我们先介绍对一维的图割操作,后面再介绍二维是如何转化到一维的。
那么对于一个图割问题,需要明确的由一下几点:
1):源点s与汇点t
如下图所示的由五个点site组成的一维情况,假设最终我们要分成两类,那么就把这两类认为是源点s与汇点t好了,那么一次类推,如果要分成多个类的话,就可以加相应的节点s或者t表示他们的类就可以了。
2):点与点之间的权值Smoothcost
从下图上也可以看出在这个一维点与点之间相连接的权值就是Smoothcost项,图中为了简化只是画出了相邻的两个点之间有一条线连接,也就是他们之间存在着权值(这里图为一个无向图,也就是权值是没有方向之分的),正常情况下,可能每两个点之间都可能存在着联系,比如如果点1与点3之间,你也可以看成他们是连接的,只不过他们之间的权值为0而已。这也是matlab里面表示这一项点与点权值的时候用一个n*n维矩阵的原因(n为点数),像这里,如果权值的大小如下定义所示的话,那么这个图的Smoothcost项的权值矩阵可以表示为:[0,5,0,0,0; 5,0,4,0,0;0,4,0,3,0;0,0,3,0,2;0,0,0,2,0];
3)点与源汇点(类点)之间的权值Datacost
除了上述的Smoothcost项之外,图割理论中还有一种项就是Datacost,表示的是各个点到源汇点(类点)之间的权值大小,为什么需要这一项呢?这一项的权值同样对于分割至关重要。比如说我们最终知道点1与点2属于s,其他店都属于t的话,那么最终优化的结果就是1-s,2-s之间的权值可能很大,而3-s,4-s,5-s之间的权值都很小,这自然在对分割最后的形式很重要了。与上面类似,Datacost自然也得有一个矩阵来表示它了,用c表示类的话(这里只有s与t那么c为2),n表示点的个数的话,那么Datacost可以表示为一个c*n的矩阵了。比如这里就可以表示为:[1 2 3 4 5; 5 4 3 2 1];
三:关于最大流最小割的实现过程
这部分曾经也细研究过,关于具体怎么解最大流最小割的方法还真不是一种,那么在假设上述的Smoothcost和Datacost定死了以后,基本上怎么切割,通过解最大流最小割问题就可以得到答案,具体的算法有一下几种,要明白算法实现过程的可以详细研究,当然其实这个过程可以通过工具箱给予解决。
§3.1Ford-Fulkerson方法(增大路径最大流算法)
§3.2Edmonds-Karp(EK)算法实现
§3.3Dinic算法
§3.4SAP算法(最短路径增广算法)
§3.5Preflow push method(预流-推进最大流方法)
详细参考如下:
http://dsqiu.iteye.com/blog/1689507
里面有详细的c语言代码,可供详细研究实现这个的过程。
四:关于matlab下解决的工具箱
这里我们使用的工具箱为Bk_matlab,这个工具箱是国外研究图割算法比较有名的机构研制的,网址为:http://vision.csd.uwo.ca/code/
在里面你可以找到关于Max-flow/min-cut这一项下的工具箱代码。
需要说明的是这里,它里面使用的是改进过的最大流最小割算法,具体怎么改进的在相应下载代码的下面有提示的相关文章,如下:
http://www.csd.uwo.ca/~yuri/Papers/pami04.pdf
这篇文章应该很经典,应该说这个教授研究图割算法的几篇文章都是经典的。
有了前面基础在使用这个工具箱基本上很简单了。它的过程基本上可以简化为:
1)创建一个割目标体h
2)设置相应的权值矩阵,包括Smoothcost和Datacost,把他们对于设置到h中。
3)最后直接使用能力最小化函数,也就是求取切割的函数,把所有需要断裂的点与点之间边的权值和未断裂的点与类之间连接的边的权值加起来认为是最后这个切割的能量,那么就是最小化这个能量了。
可以看到,这个工具箱操作还是相当简单的。下面以实例来介绍一下:
现在假设有一个图是这样的,相应的权值如下所示:
那么首先创建一个目标体,这里目标体就是创建含有多少个节点的图;
h = BK_Create(5);
从图上我们可以看到数据项datacost矩阵:
dc = [1 2 5 10 0;
3 1 2 5 4];
平滑项smoothcost项:
sc = [0 2 0 0 0;
0 0 1 0 0;
0 0 0 5 0;
0 0 0 0 5;
0 0 0 0 0];
这里为什么只有1-2的权值,而没有2-1的权值呢?由于这个工具箱认为的是图的构建是无向的,也就是只要知道了1-2,那么2-1就等于1-2了,说白了就是这个矩阵sc在程序只使用了上三角的半部分,而下三角部分是没有用的,因为他们实际上是上三角的对称嘛,所以直接省略都为0了。
有了这两个矩阵,直接使用相应的函数把矩阵加到h中即可。
BK_SetUnary(h,dc); %添加数据项
BK_SetNeighbors(h,sc); %添加平滑项
最后直接使用能量最小化函数即可:
e = BK_Minimize(h);
这样就可以求取最小化的能量(断裂的点与点之间边的权值和未断裂的点与类之间连接的边的权值和),如果想了解具体是那些边断裂的怎么办?它里面还有一个函数就是获取标签(分类)的函数:
L = BK_GetLabeling(h);
L出来的是一个n*1的矩阵,表示的是n个点各属于那些类,比如若得到L=[1 2 2 1 1];表示什么呢?它表示的就是点1和4,5是属于第一类s的,而2,3是属于第二类t的,那么也就是哪些边在断裂呢?边1-2和边3-4吧。
把上述矩阵带入matlab实验最终得到的结果是e=15,L=[1;1;2;2;2];
也就是说断裂的边是2-3;结果如下:
上图显示的是分割结果,从结果可以看到两个蓝色的框里面就是各成一类的分割方式,而绿色的边权值相加就是所谓的能量,可以看到e为1+2+1+2+5+4=15,和计算出来的一样。那么这样计算出来的断裂方式是不是最优的呢?答案是的,不然你自己去断裂其他的在计算下能量是不是比15大,随便假设断裂3-4的话,得到的能量e=1+2+5+5+5+4 = 22,大于15吧,实验其他的也是类似的。只有15是最小的了。
至此,这个工具箱求取一个已知图的最大流最小割问题就结束了,虽然大致讲了下,似乎还没有看到它的实际应用吧,那么这种方法是怎么应用到一个图像分割上面的呢?等有机会再来详谈这一部分!~_~!。
图割算法的进一步研究: