OpenCV — GrabCut с пользовательскими моделями переднего плана/фона

Я хочу использовать алгоритм GrabCut, реализованный на OpenCV.

Как показано в документации, это сигнатура функции:

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

Параметр mode указывает, как инициализировать алгоритм: либо с помощью прямоугольника (ограничивающий прямоугольник), либо с помощью маски (матрица, чья значения соответствуют пользовательским рисункам областей переднего плана/фона.

У меня уже есть цветовые модели как для FG, так и для BG, поэтому в идеале мне не нужно предоставлять маску или прямоугольник, а использовать эти модели в качестве инициализации (я хочу, чтобы OpenCV не вычислял новые модели и вместо этого использовал мои ). Я вижу, что параметры bgdModel и fgdModel каким-то образом содержат эту информацию о модели. К сожалению, документация не содержит подробностей о том, как там хранится информация о модели.

Можно ли заполнить эти модели существующими данными и запустить метод с mode=GC_EVAL?, если да, то как мне нужно кодировать модели?


person ButterDog    schedule 22.05.2014    source источник


Ответы (2)


В 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 действительно оставит модели нетронутыми, но я никогда не пробовал его с предварительно вычисленными моделями.

person RevJohn    schedule 22.05.2014
comment
Спасибо за Ваш ответ. Я просмотрел код, но что на самом деле означают эти цифры? как модель закодирована в эти значения? Передача заполненного массива — тривиальная задача, но эти значения должны иметь какой-то смысл, чтобы быть полезными. - person ButterDog; 23.05.2014

Даже у меня была похожая проблема. Вот как я это решил. Я отредактировал условие 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;

Это сработало для меня.

person aseembits93    schedule 07.10.2015