我想使用在OpenCV上实现的GrabCut算法。
如documentation所示,这是函数签名:
void grabCut(
InputArray img,
InputOutputArray mask,
Rect rect,
InputOutputArray bgdModel, // *
InputOutputArray fgdModel, // *
int iterCount,
int mode=GC_EVAL)
模式参数,指示如何使用 rect (矩形边框)或蒙版初始化算法(一个矩阵,其值对应于前景/背景区域的用户绘画。
我已经有了FG和BG的颜色模型,所以理想情况下我不需要提供遮罩或矩形,但是使用这些模型作为初始化(我想阻止OpenCV计算新模型和使用我的代替)。我看到 bgdModel 和 fgdModel 参数以某种方式包含此模型信息。不幸的是,文档没有提供关于如何在那里存储模型信息的任何细节。
是否可以使用现有数据填充这些模型并使用 mode=GC_EVAL
?运行该方法,如果是这样,我该如何编码模型?
答案 0 :(得分:3)
在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确实会使模型完好无损,但我从未尝试使用预先计算的模型。
答案 1 :(得分:1)
即使我有类似的问题。这就是我解决它的方式。 我将抓取源代码中的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是预先计算的。
您可以使用以下代码段将模型保存在.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;
这对我有用。