【问题标题】:OpenCV - GrabCut with custom foreground/background modelsOpenCV - 具有自定义前景/背景模型的 GrabCut
【发布时间】:2014-07-11 10:42:14
【问题描述】:

我想使用 OpenCV 上实现的 GrabCut 算法。

documentation所示,这是函数签名:

void grabCut(
    InputArray img, 
    InputOutputArray mask, 
    Rect rect, 
    InputOutputArray bgdModel, // *
    InputOutputArray fgdModel, // *
    int iterCount, 
    int mode=GC_EVAL) 

mode 参数,指示如何使用 rect(矩形边界框)或 ma​​sk(一个矩阵,其值对应于用户对前景/背景区域的绘制。

我已经有了 FG 和 BG 的颜色模型,所以理想情况下我不需要提供蒙版或矩形,而是使用这些模型作为初始化(我想阻止 OpenCV 计算新模型和改用我的)。我看到 bgdModelfgdModel 参数以某种方式包含此模型信息。不幸的是,文档没有提供任何细节关于模型信息是如何存储在那里的。

是否可以使用现有数据填充这些模型并使用 mode=GC_EVAL 运行该方法?,如果可以,我需要如何对模型进行编码?

【问题讨论】:

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


    【解决方案1】:

    在 opencv/sources/modules/imgproc/src/grabcut.cpp 中,您可以查看模型 (GMM) 的编码方式:

    GMM::GMM( Mat& _model )
    {
        const int modelSize = 3/*mean*/ + 9/*covariance*/ + 1/*component weight*/;
        if( _model.empty() )
        {
            _model.create( 1, modelSize*componentsCount, CV_64FC1 );
            _model.setTo(Scalar(0));
        }
        else if( (_model.type() != CV_64FC1) || (_model.rows != 1) || (_model.cols != modelSize*componentsCount) )
            CV_Error( CV_StsBadArg, "_model must have CV_64FC1 type, rows == 1 and cols == 13*componentsCount" );
    
        model = _model;
    
        coefs = model.ptr<double>(0);
        mean = coefs + componentsCount;
        cov = mean + 3*componentsCount;
    
        for( int ci = 0; ci < componentsCount; ci++ )
            if( coefs[ci] > 0 )
                 calcInverseCovAndDeterm( ci );
    }
    

    因此,您需要为每个模型提供 1 x 65 双精度的 cv::Mat(componentsCount 等于 5)。每个组件有 3 种方式,因为它在 RGB 颜色空间中计算。使用 GC_EVAL 确实会使模型完好无损,但我从未尝试过使用预先计算的模型。

    【讨论】:

    • 感谢您的回答。我已经查看了代码,但是这些数字实际上是什么意思?模型是如何编码成这些值的?传递一个填充的数组是一项微不足道的任务,但这些值需要有意义才能有用。
    【解决方案2】:

    即使我也有类似的问题。这就是我解决它的方法。 我将grabcut源代码中的GC_EVAL条件编辑到这个-

    if( mode == GC_EVAL )
       { checkMask( img, mask );
        for( int i = 0; i < iterCount; i++ )
    {
        GCGraph<double> graph;
        assignGMMsComponents( img, mask, bgdGMM, fgdGMM, compIdxs );
    
        constructGCGraph(img, mask, bgdGMM, fgdGMM, lambda, leftW, upleftW, upW, uprightW, graph );
        estimateSegmentation( graph, mask );
        return;    
    }
    }
    

    请注意,这里没有调用函数 learnGMMs。这样做是因为前台和后台 GMM 是预先计算的。

    您可以使用以下代码 sn-p 将模型保存在 .xml 文件中。

     FileStorage fs("mymodels.xml", FileStorage::WRITE);
            fs << "BgdModel" << bgdModel;
            fs << "FgdModel" << fgdModel;
    fs.release();
    

    您可以使用以下代码检索模型。

    FileStorage fs1("mymodels.xml", FileStorage::READ);
    
            fs1["BgdModel"] >> bgdModel1;
    
            fs1["FgdModel"] >> fgdModel1;
    

    这对我有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-10
      • 2019-09-15
      • 2016-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多