我正在通过GrabCut算法,我想将Gibbs能量的数据项更新为以下内容:在哪里,和。 p ^ f和p ^ b是高斯混合模型(GMM),有4和8 ……
在Graph Cuts中计算数据项是为了计算 Ť -链接。这显示在第465行的源代码中 grabcut.cpp 来源 - 特别是在 constructGCGraph 功能: https://github.com/opencv/opencv/blob/master/modules/imgproc/src/grabcut.cpp#L465 。请注意,函数的声明是 static void ,这意味着它是私人的,在外面是不可见的 cv 工作区。这意味着您无法在源代码中调用它,除非您侵入源代码本身。
grabcut.cpp
constructGCGraph
static void
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算法,其中“source”表示前景像素,“sink”表示背景像素。另请注意,有四种类型的标签。这些是在一个 enum 叫 cv::GrabCutClasses (你可以在这里找到它们: https://docs.opencv.org/3.0.0/d7/d1b/group__imgproc__misc.html#gad43d3e4208d3cf025d8304156b02ba38 )。
enum
cv::GrabCutClasses
特别:
GC_BGD
GC_FGD
GC_PR_BGD
GC_PR_FGD
GC_BGD 和 GC_FGD 是表示用于描绘图像的前景和背景笔划的像素。这些是你指定的。对于 GC_PR_BGD 和 GC_PR_FGD 因此,我们依赖于为前景和背景构建GMM并计算负对数概率。这背后的本质是,如果颜色肯定属于前景,我们将低成本绑定到接收节点,以便切割此链接以使源节点保持原样更有吸引力,从而将其分类为前景像素。您可以类似地为源节点和后台执行此操作。对于那些我们肯定知道它们是前景还是背景的像素,我们应用了高成本 lambda 到代表所需标签的链接,以便切断相反的链接,从而保留像素的所需标签。例如,如果我们知道像素是背景,我们确保 Ť - 源节点的链接成本为零,这样我们就可以在没有任何后果的情况下剪切此链接,从而确保将像素分配给背景。
lambda
要“更新”数据术语,可以通过在图像中指定更多前景和背景笔划来更好地描述您要分割的对象。如果不自己攻击源代码,就没有其他方法可以做到这一点。
最后,我建议阅读有关Graph Cuts算法如何工作的摘要: 使用maxflow进行图像分割 。它提供了更多关于GrabCut的源代码正在做什么的观点。毕竟,GrabCut只是Graph Cuts的更高级抽象。