Я хочу использовать алгоритм GrabCut, реализованный на OpenCV.
Как показано в документация это сигнатура функции:
void grabCut(
InputArray img,
InputOutputArray mask,
Rect rect,
InputOutputArray bgdModel, // *
InputOutputArray fgdModel, // *
int iterCount,
int mode=GC_EVAL)
Режим параметр указывает, как инициализировать алгоритм, либо с прямоугольник (прямоугольник ограничивающий прямоугольник) или с маскировать (матрица, значения которой соответствуют пользовательским рисункам областей переднего / заднего фона.
У меня уже есть цветовые модели для FG и BG, поэтому в идеале мне не нужно предоставлять маску или прямоугольник, а использовать эти модели в качестве инициализации (я хочу запретить OpenCV вычислять новые модели и использовать вместо них мою) ). я вижу это bgdModel а также fgdModel параметры как-то содержат эту информацию модели. Unfortunatelly, документация не содержит каких-либо подробностей о том, как информация о модели хранится там.
Можно ли заполнить эти модели существующими данными и запустить метод с mode=GC_EVAL
?, если да, то как мне нужно кодировать модели?
В 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 );
}
Таким образом, вам нужно для каждой модели cv :: Mat, равное 1 x 65, удваивается (componentsCount равно 5). Есть 3 средства на компонент, потому что его вычисления в цветовом пространстве RGB. Использование GC_EVAL действительно оставило бы модели нетронутыми, но я никогда не пробовал это делать с предварительно вычисленными моделями.
Даже у меня была похожая проблема. Вот как я это решил.
Я отредактировал условие GC_EVAL в исходном коде grabcut для этого —
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;
Это сработало для меня.