我正在研究GrabCut算法,并且想将Gibbs能量的数据项更新为以下内容:

c++ - 在GrabCut中更新吉布斯能量的数据项-LMLPHP

其中c++ - 在GrabCut中更新吉布斯能量的数据项-LMLPHPc++ - 在GrabCut中更新吉布斯能量的数据项-LMLPHP。 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算法,其中“源”表示前景像素,“接收器”表示背景像素。另请注意,标签有四种类型。这些是在称为enumcv::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_BGDGC_FGD是代表用于描绘图像的前景和背景笔触的像素。这些是您指定的。因此,对于GC_PR_BGDGC_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/

    10-11 18:28