我正在研究GrabCut算法,并且想将Gibbs能量的数据项更新为以下内容:
其中和。 p ^ f和p ^ b是分别具有4个和8个分量的高斯混合模型(GMM)。我正在遍历GrabCut的代码,可以看到在calcNWeights()函数中计算了平滑度。但是我找不到的是数据项的计算。数据项如何在代码中计算以及如何更新?
最佳答案
计算Graph Cuts中的数据项是为了计算t链接。这在grabcut.cpp
源代码的第465行的源代码中显示-特别是在constructGCGraph
函数https://github.com/opencv/opencv/blob/master/modules/imgproc/src/grabcut.cpp#L465中。请注意,该函数的声明是static void
,这意味着它是私有(private)的,在cv
工作区之外不可见。这意味着除非您侵入源代码本身,否则您将无法在源代码中调用它。
换一种说法:
// set t-weights
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 // GC_FGD
{
fromSource = lambda;
toSink = 0;
}
graph.addTermWeights( vtxIdx, fromSource, toSink );
“源”和“接收器”的术语来自Graph Cuts算法,其中“源”表示前景像素,“接收器”表示背景像素。另请注意,标签有四种类型。这些是在称为
enum
的cv::GrabCutClasses
中定义的(您可以在这里找到它们:https://docs.opencv.org/3.0.0/d7/d1b/group__imgproc__misc.html#gad43d3e4208d3cf025d8304156b02ba38)。特别:
GC_BGD
:明显的背景像素GC_FGD
:明显的前景(对象)像素GC_PR_BGD
:可能的背景像素GC_PR_FGD
:可能的前景像素GC_BGD
和GC_FGD
是代表用于描绘图像的前景和背景笔触的像素。这些是您指定的。因此,对于GC_PR_BGD
和GC_PR_FGD
,我们依靠为前景和背景构建GMM并计算负对数概率。这背后的本质是,如果颜色绝对属于前景,则我们将低成本的颜色绑定(bind)到接收器节点,以便剪切此链接以使源节点保持完整,从而将其分类为前景像素更具吸引力。 。您可以类似地对源节点和背景执行此操作。对于那些我们肯定知道它们是前景还是背景的像素,我们将高成本的lambda
应用于代表所需标签的链接,以便剪切相对的链接,从而保留该像素的所需标签。例如,如果我们知道一个像素是背景,则确保到源节点的t-link成本为零,这样我们就可以切断该链接而不会产生任何后果,从而确保将像素分配给了背景。要“更新”数据项,可以通过在图像中指定更多前景和背景笔划来完成,以更好地描述您要分割的对象。没有自己动手破解源代码,别无其他方法。
最后一点,我建议阅读有关Graph Cuts算法工作原理的摘要:Image segmentation with maxflow。它为GrabCut的源代码在做什么提供了更多视角。毕竟,GrabCut仅仅是Graph Cuts的更高层次的抽象。
关于c++ - 在GrabCut中更新吉布斯能量的数据项,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54977167/