OpenCV: вывод функции прогнозирования максимизации ожидания

Фон:
У меня есть 2 набора цветных пикселей из изображения, один соответствует фону, другой соответствует переднему плану. Затем я обучаю 2 модели гауссовой смеси, используя EM из OpenCV для каждого набора. Моя цель — найти вероятность того, что случайный пиксель окажется на переднем плане и на заднем плане. Таким образом, я использую функцию «прогнозировать» для каждого EM на моем пикселе.

Вопрос:

  • Я не понимаю значения, возвращаемые этой функцией. В документации OpenCV написано:

Метод возвращает двухэлементный двойной вектор. Нулевой элемент — это логарифмическое значение правдоподобия для выборки. Первый элемент — это индекс наиболее вероятного компонента смеси для данного образца.

http://docs.opencv.org/modules/ml/doc/expectation_maximization.html?highlight=predict#Vec2d%20EM::predict%28InputArray%20sample,%20OutputArray%20probs%29%20const

Я не понимаю, что означает «логарифм правдоподобия». В моих результатах иногда встречаются отрицательные значения и значения> 1. Кто-нибудь, кто использовал одну и ту же функцию, имеет такие результаты или результаты в диапазоне от 0 до 1? Что я могу сделать из своих результатов?

  • Как я могу получить вероятность того, что пиксель будет принадлежать всему GMM (а не вероятность принадлежать каждому кластеру GMM)?

Вот мой код:

Mat mask = imread("mask.tif", 0);
Mat formerImage = imread("ImageFormer.tif");
Mat currentImage = imread("ImageCurrent.tif");

// number of cluster in the GMM
int nClusters = 5;

int countB=0, countF=0;

Vec3b color;

Vec2d probFg, probBg; // probabilities to belong to the foreground or background from GMMs

//count the number of pixels for each training data
for(int c=0; c<=40;c++) {
for(int l=0; l<=40;l++) {
if(mask.at<BYTE>(l, c)==255) {
countF++;
} else if(mask.at<BYTE>(l, c)==0) {
countB++;
}
}
}printf("countB %d countF %d \n", countB, countF);

Mat samplesForeground = Mat(countF,3, CV_64F);

Mat samplesBackground = Mat(countB,3, CV_64F);// Expectation-Maximisation able to resolve the GMM and to predict the probability for a pixel to belong to the GMM.
EM em_foreground= EM(nClusters);
EM em_background= EM(nClusters);

countB=0;
countF=0;

// fill the training data from the former image depending of the mask
for(int c=0; c<=40;c++) {
for(int l=0; l<=40;l++) {
if(mask.at<BYTE>(l, c)==255) {
color = formerImage.at<Vec3b>(l, c);
samplesForeground.at<double>(countF,0)=color[0];
samplesForeground.at<double>(countF,1)=color[1];
samplesForeground.at<double>(countF,2)=color[2];
countF++;
} else if(mask.at<BYTE>(l, c)==0) {
color = formerImage.at<Vec3b>(l, c);
samplesBackground.at<double>(countB, 0)=color[0];
samplesBackground.at<double>(countB, 1)=color[1];
samplesBackground.at<double>(countB, 2)=color[2];
countB++;
}
}
}

printf("countB %d countF %d \n", countB, countF);
em_foreground.train(samplesForeground);
em_background.train(samplesBackground);

Mat sample(1, 3, CV_64F);

// try every pixel of the current image and get the log likelihood
for(int c=0; c<=40;c++) {
for(int l=0; l<=40;l++) {
color = currentImage.at<Vec3b>(l,c);
sample.at<double>(0)=color[0];
sample.at<double>(1)=color[1];
sample.at<double>(2)=color[2];
probFg=em_foreground.predict(sample);
probBg=em_background.predict(sample);
if(probFg[0]>0 || probBg[0]>0)
printf("probFg[0] %f probBg[0] %f \n", probFg[0], probBg[0]);
}
}

РЕДАКТИРОВАТЬ

После того, как @BrianL объяснил, я теперь понимаю вероятность регистрации.

Моя проблема заключается в том, что логарифмическая вероятность функции предсказания иногда> 0. Но это должно быть <= 0. Кто-нибудь сталкивался с этой проблемой раньше?

Я отредактировал код выше, чтобы показать проблему. Я попробовал программу с изображениями ниже:

Первое изображение — это ImageCurrent.tif, второе — это ImageFormer.tif, а последнее — mask.tif.

текущее изображение
прежнее изображение
маскировать

Это можно считать ошибкой в ​​OpenCV? Должен ли я открыть тикет на трекере ошибок OpenCV?

5

Решение

Насколько я понимаю, у вас есть два отдельных GMM для переднего и фонового участков изображения. Общая вероятность того, что образец пикселя ‘x’ в тестовом изображении при оценке на переднем плане GMM составляет

P_fg(x) = sum_over_j_1_to_k ( Wj_fg * Pj_fg( x ))
where
k = number of clusters in foreground GMM
x = test sample
Pj_fg(x) = probability that sample x is in j-th  cluster according to the foreground GMM
Wj_fg = weight of the j-th cluster in foreground GMM
also, sum of all weights should be 1 for each GMM.

Мы можем сделать аналогичный расчет для фона GMM.

Если посмотреть на код EM в opencv, то похоже, что первая часть из двух значений, которые возвращает EM, является логарифмической вероятностью. Для переднего плана GMM это

log(P_fg(x_i))

Я реализовал ваш алгоритм и для каждого пикселя в тестовом изображении сравнил правдоподобие, возвращаемое для каждого из двух GMM, и классифицировал пиксель с GMM с более высоким значением. Я получил достойные результаты.

В этом отношении, да, это значение указывает на принадлежность пикселя ко всему GMM.

2)
В моей реализации вашей проблемы я всегда получал логарифмические правдоподобия всех GMMS всех пикселей тестового образца ниже 0.

1

Другие решения

«Логарифм правдоподобия» означает логарифм вероятности. Так как для вероятности п мы ожидаем 0 ≤ п ≤ 1, я ожидаю, что значения будут отрицательными: log (п) ≤ 0. Большие отрицательные числа означают меньшие вероятности.

Эта форма полезна, когда вы имеете дело с продуктами с очень малой вероятностью: если вы умножите обычным образом, вы можете легко получить недостаточное значение и потерять точность, потому что вероятность становится очень маленькой. Но в лог-пространстве умножение превращается в сложение, которое повышает точность, а также потенциально скорость вычисления.

predict Функция предназначена для классификации точки данных. Если вы хотите дать оценку, какова вероятность того, что любой компонент в модели, вы можете использовать параметры модели (см. get документация) рассчитать самостоятельно.

4

Я заметил, что вы делаете сегментацию изображений на основе графа.

Возможно, вы захотите взглянуть на следующий пост в блоге, в котором OpenCV и его класс GMM очень похожи на то, что вы делаете для выполнения сегментации изображений на основе разрезов на графике. Код дан на C ++ с подробными пояснениями. Вот ссылка: ссылка на сайт

По сути, я могу только сказать, что вероятность логарифма, правильная она или нет, не та, которую вы ищете. Проверьте вышеуказанную ссылку для деталей.

1
По вопросам рекламы [email protected]