Фоновая сегментация переднего плана на основе электромагнитной кластеризации в OPENCV

Я попытался выполнить сегментацию переднего плана на основе ЭМ, используя приведенный ниже код ... который я также нашел в Stackoverflow .... Но, похоже, где-то есть какая-то ошибка, поскольку я никогда не вижу, чтобы второй оператор printf выполнялся .... в основном он никогда не достигает части кода, относящейся к классификации / кластеризации. Код приведен ниже. Может ли кто-нибудь помочь мне в этом?

#include <opencv2/opencv.hpp>
#include <opencv2/legacy/legacy.hpp>


char str1[60];

int main()
{

    cv::Mat source = cv::imread("C:\\Image Input\\part1.bmp" ); 
    if(!source.data)
        printf(" No data \n");
    //ouput images
    cv::Mat meanImg(source.rows, source.cols, CV_32FC3);
    cv::Mat fgImg(source.rows, source.cols, CV_8UC3);
    cv::Mat bgImg(source.rows, source.cols, CV_8UC3);

    //convert the input image to float
    cv::Mat floatSource;
    source.convertTo(floatSource, CV_32F);

    //now convert the float image to column vector
    cv::Mat samples(source.rows * source.cols, 3, CV_32FC1);
    int idx = 0;
    for (int y = 0; y < source.rows; y++) {

        cv::Vec3f* row = floatSource.ptr<cv::Vec3f > (y);
        for (int x = 0; x < source.cols; x++) {
            samples.at<cv::Vec3f > (idx++, 0) = row[x];
        }
    }
    printf(" After Loop \n");
    //we need just 2 clusters
    cv::EMParams params(2);
    cv::ExpectationMaximization em(samples, cv::Mat(), params);

    //the two dominating colors
    cv::Mat means = em.getMeans();
    //the weights of the two dominant colors
    cv::Mat weights = em.getWeights();

    //we define the foreground as the dominant color with the largest weight
    const int fgId = weights.at<float>(0) > weights.at<float>(1) ? 0 : 1;
    printf(" After Training \n");
    //now classify each of the source pixels
    idx = 0;
    for (int y = 0; y < source.rows; y++) 
    {
        printf(" Now Classify\n");
        for (int x = 0; x < source.cols; x++)
        {


            //classify
            const int result = cvRound(em.predict(samples.row(idx++), NULL));
            //get the according mean (dominant color)
            const double* ps = means.ptr<double>(result, 0);

            //set the according mean value to the mean image
            float* pd = meanImg.ptr<float>(y, x);
            //float images need to be in [0..1] range
            pd[0] = ps[0] / 255.0;
            pd[1] = ps[1] / 255.0;
            pd[2] = ps[2] / 255.0;

            //set either foreground or background
            if (result == fgId) {
                fgImg.at<cv::Point3_<uchar> >(y, x, 0) = source.at<cv::Point3_<uchar> >(y, x, 0);
            } else {
                bgImg.at<cv::Point3_<uchar> >(y, x, 0) = source.at<cv::Point3_<uchar> >(y, x, 0);
            }
        }
    }

    printf(" Show Images \n");
    cv::imshow("Means", meanImg);
    cv::imshow("Foreground", fgImg);
    cv::imshow("Background", bgImg);
    cv::waitKey(0);

    return 0;
}

person noviceS    schedule 01.06.2014    source источник
comment
Спасибо за ваш любезный ответ, однако он дает мне ошибку компиляции, если я инициализирую матрицы с 0, как вы упомянули ... другая вещь - const int fgId = weights.at ‹float› (0) ›weights.at ‹float› (1)? 0: 1; эта строка также выдает ошибку во время выполнения. Так что если просто инициализировать int fgId равным 0 или 1, тогда все будет нормально .... Вы можете сказать мне, почему? В чем проблема !!!   -  person noviceS    schedule 02.06.2014


Ответы (1)


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

Всего 1 коррекция, инициализируйте изображения нулями:

//ouput images
cv::Mat meanImg=Mat::zeros(source.rows, source.cols, CV_32FC3);
cv::Mat fgImg=Mat::zeros(source.rows, source.cols, CV_8UC3);
cv::Mat bgImg=Mat::zeros(source.rows, source.cols, CV_8UC3);

введите описание изображения здесь

person Andrey Smorodov    schedule 01.06.2014