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

标签 c++ opencv image-processing computer-vision image-segmentation

我正在浏览 GrabCut算法,我想将吉布斯能量的数据项更新为以下内容:

eq

其中,frbg . p^f 和 p^b 分别是具有 4 个和 8 个分量的高斯混合模型 (GMM)。我正在查看 GrabCut 的代码,我可以看到平滑度是在 calcNWeights() 函数中计算的。但是我找不到的是数据项的计算。数据项在代码中是如何计算的,如何更新?

最佳答案

计算Graph Cuts中的数据项就是计算t-links。这显示在 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 );

“source”和“sink”的术语来自 Graph Cuts 算法,其中“source”表示前景像素,“sink”表示背景像素。另请注意,有四种类型的标签。它们在名为 cv::GrabCutClassesenum 中定义(您可以在此处找到它们: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 链接成本为零,这样我们就可以切断该链接而不会产生任何后果,确保该像素被分配给背景。

要“更新”数据项,可以通过在图像中指定更多的前景和背景笔划来更好地描述您尝试分割的对象。如果不亲自侵入源代码,就没有其他方法可以做到这一点。

作为最后的说明,我建议您阅读有关 Graph Cuts 算法工作原理的摘要:Image segmentation with maxflow .它提供了有关 GrabCut 源代码正在做什么的更多视角。毕竟,GrabCut 只是 Graph Cuts 的更高级抽象。

关于c++ - 在 GrabCut 中更新吉布斯能量的数据项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54977167/

相关文章:

c++ - OO编程设计题: Global Object part II

c++ - OpenCV imread 不起作用

android - OpenCV 示例 - 颜色 Blob 检测

ios - OpenGL ES 2.0 损失图像质量

c++ - 弯路捕捉质感

c++ - 在 C++ 中移动 unique_ptr

c++ - 构造函数不能是虚拟的

c++ - OpenCV 中具有公差的模板匹配

opencv - Teensy +红外摄像机+ OpenCV

python - 如何通过检测直线检测主体结构轮廓