graph cut使用

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(i, j);

            //加t-link,source是背景点,sink是前景点
            double fromSource, toSink;
            //如果可能是前景或者背景
            if (mask.at(p) == GC_PR_BGD || mask.at(p) == GC_PR_FGD)
            {   
                fromSource = -log(bgdGMM(color));
                toSink = -log(fgdGMM(color));
            }//已经确定是背景
            else if (mask.at(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;
            }
        }
    }
}

新的结果
graph cut使用_第1张图片

opencv的版本
graph cut使用_第2张图片

略微差别,前后框手画的,结果应该是正确的,opencv的算法和这个应该是一模一样的,其实写法都一样。

你可能感兴趣的:(算法)