最大流最小割算法求解的能量方程,通常是基于图结构得到的能量求解方法,这类能量方程可以普遍表示为:
其中L是图像P的一个标签结果。设P为3*3的图像,P = [ 3, 8, 9; 4, 9, 8; 2, 9, 7 ],现在要将P的像素分为两类,标签值为1或2,L是P的所有可能性中的一种可以是L = [ 1, 2, 2; 1, 2, 2; 1, 2, 2 ] 或 L = [ 1, 1, 2; 1, 2, 2; 2, 2, 2 ](还有很多就不枚举了),L的所有可能性即为2^9,而能量方程 E(L) 就是计算在当前标签结果下的能量值,通常我们将能量方程最小化,从而求出可以使得总体能量最小的标签值情况L,利用最终的像素分类结果得到图像分割等结果。如下图所示,(a)为图像P的像素灰度值示意图,颜色越深则灰度值越小;(b)为该图像的一种分类结果L,当然还存在着若干种分类结果L,我们要做的就是设计一个相较周全的能量方程,然后通过最大流/最小割方法进行最小化求解。
有向图G = < V, E >由节点V和节点间的边E构成。通常来说,图中的节点对应图像的像素或超像素、超体素。图通常还包含一些额外附加但非常重要的点,称为终端节点(terminals)。终端节点的重要性在于,它们可以直接连接图中节点,从而给每个节点赋予标签,意味着每个终点表示一个标签值,例如图中有两个终点,则该图像最终只会被分为两种标签值。
以下用包含两个终点的图结构进行更详细的解释,两个终点(terminals)在图结构G中通常成为源点(Source,缩写为s)和汇点(Sink,缩写为t)。
如上图所示,P为3*3的图像,现在要将它的像素划分为s和t两个标签值的子集。图(a)为各节点与源点汇点、节点间的连接关系示意图;图(b)中的cut是图割的示意,通过能量方程的最小化求解,得到图像P的最小割,将不必要节点间的边割断,源点和汇点所连接点的集合的交为空,并为P中所有节点
from pygraph.classes.digraph import digraph
from pygraph.algorithms.minmax import maximum_flow
gr = digraph()
gr.add_nodes([0,1,2,3])
gr.add_edge((0,1), wt=4)
gr.add_edge((1,2), wt=3)
gr.add_edge((2,3), wt=5)
gr.add_edge((0,2), wt=3)
gr.add_edge((1,3), wt=4)
flows,cuts = maximum_flow(gr, 0, 3)
print ('flow is:' , flows)
print ('cut is:' , cuts)
# -*- coding: utf-8 -*- from scipy.misc import imresize from PCV.tools import graphcut from PIL import Image from numpy import * from pylab import * im = array(Image.open("empire.jpg")) im = imresize(im, 0.07) size = im.shape[:2] print ("OK!!") # add two rectangular training regions labels = zeros(size) labels[3:18, 3:18] = -1 labels[-18:-3, -18:-3] = 1 print ("OK!!") # create graph g = graphcut.build_bayes_graph(im, labels, kappa=1) # cut the graph res = graphcut.cut_graph(g, size) print ("OK!!") figure() graphcut.show_labeling(im, labels) figure() imshow(res) gray() axis('off') show()
实验截图