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

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

Вопрос:

  • Я не понимаю значения, возвращаемые этой функцией. В документации 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.

текущее изображениепрежнее изображение mask

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


person Community    schedule 09.01.2013    source источник


Ответы (3)


Насколько я понимаю, у вас есть два отдельных 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.

person Community    schedule 27.11.2015

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

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

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

person Brian L    schedule 10.01.2013
comment
Извините, что беспокою вас, но вы видите какие-либо проблемы в коде выше? Я до сих пор не понимаю, как функция прогнозирования может вернуть мне логарифм вероятности выше нуля. - person Seltymar; 06.02.2013
comment
кажется, что, например, color[2]/255.0 не правильно и приводит к ошибке. - person Seltymar; 06.02.2013
comment
Почему вы делите на 255? Это то же самое, что вы сделали с тренировочными данными? Кроме того, почему вы переключаете индексы - color[2/1/0] переходит на sample(0/1/2)? Кажется, в вашем коде происходит ряд вещей, поэтому я не уверен, какую конкретно ошибку вы получаете. Функция predict возвращает двухэлементный вектор; первый элемент — это классификация, а второй элемент — логарифмическая вероятность. Второй элемент никогда не должен быть положительным, но первый может быть. - person Brian L; 07.02.2013
comment
На самом деле я делю на 255, потому что у меня есть 3 канала с 8-битным цветным изображением. Поэтому я хотел нормализовать свои данные, но в этом нет необходимости (то же самое и для данных обучения). Поскольку Opencv всегда читает изображение в формате BGR, это было просто для того, чтобы формат RGB соответствовал моему коду, но я изменил это и теперь имею color[0/1/2]. Из документации predict docs.opencv.org /modules/ml/doc/ нулевой элемент — это вероятность логирования, и именно его я и ищу. Должен ли я редактировать свой код или открыть новый вопрос? У меня все еще есть проблема. - person Seltymar; 07.02.2013

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

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

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

person Community    schedule 21.02.2013
comment
Спасибо за ссылку. Но я не хочу строить граф-разрез. Так как я уже знаю цвет для моего переднего плана и фона, я пытаюсь сгруппировать их и определить принадлежность к одному и другому GMM. Но после этого я не использую графическую обрезку. Я пытаюсь реализовать пункт 2.1 из этой статьи juew.org/projects/SnapCut/snapcut.htm (это проект страницы, вы можете выбрать качество pdf). Я попытаюсь вычислить вероятность, используя вес и вероятность каждого кластера. - person Seltymar; 21.02.2013
comment
На самом деле, это не может работать, используя вероятность каждого кластера и вес. Сумма весов равна 1, и сумма вероятностей тоже равна 1. например, если у меня в GMM есть 2 кластера с весами (0,6 и 0,4). Теперь у меня есть пиксель, очень далекий от GMM в цветовом пространстве, но с вероятностью принадлежать каждому кластеру (0,5 и 0,5), у меня будет вероятность 0,3. Но на самом деле я должен получить что-то близкое к 0, так как это очень далеко. Вот почему я хотел, чтобы вероятность принадлежала всему GMM. - person Seltymar; 21.02.2013
comment
Привет. Я намерен дать ссылку, чтобы показать вам, как авторы кода сегментации изображения на основе graphcut использовали GMM для вычисления вероятности того, что образец пикселя принадлежит цветовой модели переднего плана/фона. По сути, я говорю, что вероятность, которую вы получили, вызвав метод прогнозирования класса GMM, не является тем, что вы ищете. Однако код сегментации GC делает это, так что проверьте его. Надеюсь это поможет. - person lightalchemist; 21.02.2013
comment
Но из его кода я понимаю, что он берет наивысшую вероятность, умножая вес на вероятность каждого кластера.for(int g=0;g<num_gaussians;g++) p = max(p,w[g]*(double)(((float*)xprob.data)[g])). И взять модель с наибольшей вероятностью. Как я уже говорил выше, мой пиксель может быть очень далек от GMM, но все же получить высокую вероятность и взаимность. Кроме того, я не хочу классифицировать все пиксели с помощью метки, я просто хочу найти, какой из них обязательно является передним планом, а какой — фоновым. - person Seltymar; 21.02.2013
comment
Если я возьму только вероятность принадлежит к переднему плану (с 1 GMM). У меня будет ошибка, когда цвет переднего плана и цвета фона похожи. - person Seltymar; 21.02.2013
comment
Возможно, я неправильно понял, что вероятность рассчитывается в статье Video Snapcut. - person Seltymar; 22.02.2013
comment
Это не сегментация на основе графического разреза. - person koshy george; 27.11.2015