Обновление данных слагаемых энергии Гиббса в GrabCut - PullRequest
0 голосов
/ 04 марта 2019

Я проходил алгоритм GrabCut и хотел обновить термин данных энергии Гиббса следующим образом:

eq

, где fr и bg.p ^ f и p ^ b - модель гауссовой смеси (GMM) с 4 и 8 компонентами соответственно.Я просматривал код GrabCut , где я вижу, что плавность вычисляется в функции calcNWeights () .Но то, что я не смог найти, это вычисление термина данных.Как рассчитывается срок данных в коде и как его обновлять?

1 Ответ

0 голосов
/ 04 марта 2019

Вычисление термина данных в Graph Cuts - это вычисление t -линков.Это показано в исходном коде в строке 465 источника grabcut.cpp - в частности, в функции constructGCGraph: https://github.com/opencv/opencv/blob/master/modules/imgproc/src/grabcut.cpp#L465. Обратите внимание, что объявление функции static void, что означает, что она является закрытой, а невидимый вне рабочей области 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 );

Терминология «источник» и «сток»происходят из алгоритма Graph Cuts, где «источник» означает пиксель переднего плана, а «приемник» означает пиксель фона.Также обратите внимание, что существует четыре типа этикеток.Они определены в enum под названием cv::GrabCutClasses (вы можете найти их здесь: 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_BGD и GC_FGD - это пиксели, которые обозначают передний план и фоновые обводки, используемые для разграничения изображения. Это то, что вы указываете. Для GC_PR_BGD и GC_PR_FGD мы, таким образом, полагаемся на построение GMM для переднего плана и фона.и вычислим отрицательные логарифмические вероятности. Суть этого в том, что если цвет определенно принадлежит переднему плану, мы назначаем дешевую привязку его к узлу приемника, чтобы было более привлекательным вырезать эту ссылку, чтобы оставить исходный узел нетронутым,таким образом, классифицируя его как пиксель переднего плана. Вы можете аналогичным образом сделать это для исходного узла и фона. Для тех пикселей, где мы точно знаем, являются ли они передним планом или фоновым.d, мы применяем высокую стоимость lambda к ссылке, представляющей желаемую метку, чтобы противоположная ссылка была обрезана, тем самым сохраняя желаемую метку для пикселя.Например, если мы знаем, что пиксель является фоновым, мы гарантируем, что стоимость ссылки t на исходный узел равна нулю, чтобы мы могли обрезать эту ссылку без каких-либо последствий, гарантируя, что пиксель назначен наbackground.

Чтобы «обновить» термины данных, это делается путем указания большего количества передних и фоновых штрихов на изображении, чтобы дать лучшее описание объекта, который вы пытаетесь сегментировать.Нет другого способа сделать это без взлома исходного кода самостоятельно.

В качестве заключительного замечания я бы рекомендовал прочитать это резюме о том, как работает алгоритм Graph Cuts: Сегментация изображения с maxflow .Это дает больше перспективы того, что делает исходный код для GrabCut.В конце концов, GrabCut - это просто абстракция Graph Cuts более высокого уровня.

...