graph cut下载地址
maxflow3.01
使用方法:
//初始化GC图
Graph< typename captype, typename tcaptype, typename flowtype > g;
这里的3个type必须要相同,不然会报unresoveled external的错误
//增加节点,返回标号
int vtxInd = g.add_node()
//增加n-links,这里是相互建立,一般其实就无向就行了,切割的时候,所以2个权值都是w
g.add_edge(vtxInd1,vtxInd2,w,w)
//增加t-links,fromSource:到S节点的权值 toSink:到T节点的权值
graph->add_tweights(vtxIdx, fromSource, toSink);
//计算最小割
g.maxflow()
//判断节点被割在S还是T,2个值
g.what_segment(vtxInd)
SOURCE = 0,
SINK = 1
Test:
这里在Grabcut上做测试,用这个代码来进行图的建立
建图
static void myConstructGCGraph(const Mat& img, const Mat& mask, const GMM& bgdGMM, const GMM& fgdGMM, double lambda,
const Mat& leftW, const Mat& upleftW, const Mat& upW, const Mat& uprightW, Graph<double, double, double> *graph)
{
Point p;
for (int i = 0; i < img.rows; i++)
for (int j = 0; j < img.cols; j++)
{
//加节点
p.y = i;
p.x = j;
int vtxIdx = graph->add_node();
Vec3b color = img.at<Vec3b>(i, j);
//加t-link,source是背景点,sink是前景点
double fromSource, toSink;
//如果可能是前景或者背景
if (mask.at<uchar>(p) == GC_PR_BGD || mask.at<uchar>(p) == GC_PR_FGD)
{
fromSource = -log(bgdGMM(color));
toSink = -log(fgdGMM(color));
}//已经确定是背景
else if (mask.at<uchar>(p) == GC_BGD)
{
fromSource = 0;
toSink = lambda;
}
else
{
fromSource = lambda;
toSink = 0;
}
graph->add_tweights(vtxIdx, fromSource, toSink);
//加n-link,
// * * *
// * P
double w;
//加与(x,y-1)的连接边
if (i > 0)
{
w = upW.at<double>(i - 1, j);
graph->add_edge(vtxIdx, vtxIdx - img.cols, w, w);//来回的边的权值一样?
}
//加与(x-1,y-1)的连接边
if (i > 0 && j > 0)
{
w = upleftW.at<double>(i - 1, j - 1);
graph->add_edge(vtxIdx, vtxIdx - img.cols - 1, w, w);
}
//加与(x-1,y)的连接边
if (j > 0)
{
w = leftW.at<double>(i, j - 1);
graph->add_edge(vtxIdx, vtxIdx - 1, w, w);
}
//加与(x+1,y - 1)的连接边
if (i > 0 && j < img.cols - 1)
{
w = uprightW.at<double>(i - 1, j + 1);
graph->add_edge(vtxIdx, vtxIdx - img.cols + 1, w, w);
}
}
}
计算割并保存结果
static void estimateSegmentation(Graph<double, double, double> * graph, Mat& mask)
{
graph->maxflow();
Point p;
for (p.y = 0; p.y < mask.rows; p.y++)
{
for (p.x = 0; p.x < mask.cols; p.x++)
{
if (mask.at<uchar>(p) == GC_PR_BGD || mask.at<uchar>(p) == GC_PR_FGD)
{
if (graph->what_segment(p.y*mask.cols + p.x /*vertex index*/) == Graph<double, double, double>::SOURCE)
mask.at<uchar>(p) = GC_PR_FGD;
else
mask.at<uchar>(p) = GC_PR_BGD;
}
}
}
}
新的结果
opencv的版本
略微差别,前后框手画的,结果应该是正确的,opencv的算法和这个应该是一模一样的,其实写法都一样。