Использование изображения PNG в качестве маски для GrabCut

У меня есть изображение png с зелеными и красными линиями и прозрачным фоном, которое мне нужно использовать в качестве маски для выполнения GrabCut. Но я получаю неожиданные результаты. Вот мой код:

//find the mask
Mat mask;
mask.create( image.size(), CV_8UC1);
mask.setTo(Scalar::all(GC_BGD));
Mat maskImg = imread("messi5.png");

for(int i=0; i<maskImg.cols; i++)    
    for(int j=0; j<maskImg.rows; j++)    
    {               
        //if it's red, make it white
        if ((int)maskImg.at<cv::Vec3b>(j,i)[0]==0 && (int)maskImg.at<cv::Vec3b>(j,i)[1] == 0 && (int)maskImg.at<cv::Vec3b>(j,i)[2] == 255) {

            mask.at<cv::Vec3b>(j,i)[0]= GC_BGD;
            mask.at<cv::Vec3b>(j,i)[1] = GC_BGD;
            mask.at<cv::Vec3b>(j,i)[2] = GC_BGD;
        }           

        //if it's green, make it black
        if ((int)maskImg.at<cv::Vec3b>(j,i)[0]==0 && (int)maskImg.at<cv::Vec3b>(j,i)[1] == 255 && (int)maskImg.at<cv::Vec3b>(j,i)[2] == 0) {    
            mask.at<cv::Vec3b>(j,i)[0] = GC_FGD;
            mask.at<cv::Vec3b>(j,i)[1] = GC_FGD;
            mask.at<cv::Vec3b>(j,i)[2] = GC_FGD;
        }
    }

 ...

Вот результат: http://prntscr.com/40kt4e. Я предполагаю, что прямоугольника нет, он видит только пиксели GC_FGD, все остальное считается BG. И выглядит как-то масштабно, но я понятия не имею, как это исправить.


person nena    schedule 08.07.2014    source источник


Ответы (1)


я пытался сказать в

Маска чтения GrabCut из файла PNG в OpenCV (C++ )

что вы используете 3-канальный аксессуар для 1-канального изображения. это немного испортит ситуацию, используйте 1-канальную версию для 1-канальной маски:

    Mat image;
    image= cv::imread(file);

    //everything outside this box will be set to def. 
    //background GC_BGD, clearly from the image you can see that the players legs are outside the box, 
    //so this will cause problems. you need to either change the box, 
    //such that everything is outside the box is the background, or use your mask to scribble on the players legs in green.  
    cv::Rect rectangle(startX, startY, width, height);  
    cv::Mat bgModel,fgModel;

    //find the mask
    Mat mask;
    mask.create( image.size(), CV_8UC1);  //CV_8UC1 is single channel
    mask.setTo(Scalar::all(GC_BGD));  //you have set it to all def. background 

    Mat maskImg = imread("messi5.png");


    for(int i=0; i<maskImg.cols; i++)    
        for(int j=0; j<maskImg.rows; j++)    
        {               
            //if it's red, make it black
            if ((int)maskImg.at<cv::Vec3b>(j,i)[0]==0 && (int)maskImg.at<cv::Vec3b>(j,i)[1] == 0 && (int)maskImg.at<cv::Vec3b>(j,i)[2] == 255) {

                //the whole mask is black so this is redundant
                mask.at<uchar>(j,i)= GC_BGD;  //GC_BGD := 0 := black 

            }           

            //if it's green, make it white
            if ((int)maskImg.at<cv::Vec3b>(j,i)[0]==0 && (int)maskImg.at<cv::Vec3b>(j,i)[1] == 255 && (int)maskImg.at<cv::Vec3b>(j,i)[2] == 0) {    

                    mask.at<uchar>(j,i) = GC_FGD; //GC_FGD:= 1 := white 

            }
        }

Более эффективный код для циклического просмотра изображений см. на странице http://docs.opencv.org/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html

Функция LUT может помочь здесь: http://docs.opencv.org/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html#the-core-function

person QED    schedule 08.07.2014
comment
Это прекрасно работает, но очень медленно для изображений с большим разрешением? Есть ли у вас какие-либо предложения по улучшению производительности, помимо запуска на графическом процессоре? - person nena; 21.07.2014
comment
Привет, если вы имеете в виду именно этот цикл, то вы можете получить доступ к данным напрямую, а не с помощью функции .at. Если вы имеете в виду GrabCut, то, боюсь, нет, так как это означало бы ускорение резки графа, что по сути является максимальным потоком, поэтому вы вводите тяжелый комп. наука там работает. - person QED; 22.07.2014
comment
stackoverflow.com/questions/8963617 / - person QED; 22.07.2014
comment
@QUED Думаю, мне следует попробовать параллельное программирование, я думаю, это лучший способ повысить производительность. Можете ли вы дать мне какие-либо указания, просто чтобы знать, с чего начать? - person nena; 25.07.2014
comment
Привет, если вы действительно хотите это сделать, то, возможно, начните здесь: Параллельные и распределенные сокращения графов с помощью двойной декомпозиции, lup.lub.lu.se/luur/. Также рассмотрим кудакуты, а также многомасштабные пирамиды с распространением раствора от крупного к мелкому. В противном случае, возможно, посмотрите на альтернативы интерактивной сегментации изображений, которые не используют разрезание графика. - person QED; 25.07.2014