Наполнение C ++ - PullRequest
       31

Наполнение C ++

3 голосов
/ 30 ноября 2011

У меня проблема с реализацией заливки.
Задача состоит в том, чтобы попросить пользователя нажать на белую часть изображения (с указанием начальной точки), которую он хочет заполнить черным.
Операция должна выполняться на двоичных изображениях.
Я использую библиотеку CImg .
Я не могу использовать рекурсивный алгоритм.
Я что-то придумал, но это не работает должным образом (разрыв становится черным только в начальной точке).Я совсем не знаком с очередями, поэтому, возможно, проблема в их реализации.

void floodfill(int x, int y, int c, int b, CImg <unsigned char>image)
{
    //c-black
    //b-white
    CImg<unsigned char> kopia(image.width(),image.height());

    for (int p=1; p<image.height()-1; p++)
    {
        for (int q=1; q<image.width()-1; q++)
        {
            kopia(p,q)=255; //setting kopia2 all white
        }
    }

    queue <pair<int,int> > a;
    int p;
    if(image(x, y) == c)
    {
        cout<<"Already black"<<endl;
        return;
    }
    else
    {
        a.push(make_pair(x, y));
        while(!a.empty())
        {
            a.pop();
            p=image(x+1, y);
            if((p == b) && (x < image.width()))
            {
                a.push(make_pair(x+1, y));
                kopia(x+1, y)=c;
                image(x+1, y)=c;
            }
            p = image(x-1, y);
            if((p == c) && (x > 0))
            {
                a.push(make_pair(x-1, y));
                kopia(x-1, y)=c;
                image(x-1, y)=c;
            }
            p=image(x, y+1);
            if((p == b) && (y < image.height()))
            {
                a.push(make_pair(x, y+1));
                kopia(x, y+1)=c;
                image(x, y+1)=c;
            }
            p=image(x, y-1);
            if((p == b) && (y > 0))
            {
                a.push(make_pair(x, y-1));
                kopia(x, y-1)=c;
                image(x, y-1)=c;
            }
        }
        saving(kopia);
    }
}

void hole (CImg <unsigned char>image)
{
    CImgDisplay image_disp(image,"Click a point");

    int c_x=0; //coordinates
    int c_y=0;

    while (!image_disp.is_closed())
    {
        image_disp.wait();
        if (image_disp.button())
        {
            c_x=image_disp.mouse_x();  //reads coordinates indicated by user
            c_y=image_disp.mouse_y();
        }
    }

    floodfill(c_x, c_y,0,255,image);
}

Ответы [ 3 ]

1 голос
/ 30 ноября 2011

Разве вы не понимаете, что работаете с одними и теми же x и y все время и что a.pop() ничего не возвращает? std::queue::pop только выводит переднюю часть очереди, но не возвращает ее. Вы должны запросить его заранее, используя std::queue::front. Так что просто добавьте

x = a.front().first;
y = a.front().second;

прямо перед a.pop() внутри цикла while.

И, между прочим, вы также можете установить image(x, y) (и, возможно, kopia(x, y)) в c в начале блока else перед нажатием начальной пары, хотя это также может быть установлено соседями. итераций.

1 голос
/ 30 ноября 2011

Также в CImg есть встроенная функция, которая делает то, что вы хотите: CImg :: draw_fill ().

1 голос
/ 30 ноября 2011

1)

    while(!a.empty())
    {
        x = a.front().first; //fixed as per ChristianRau's code
        y = a.front().second; //fixed as per ChristianRau's code
        a.pop();

Вы только что вытолкнули текущие координаты x, y из стека, не глядя на то, чем они были.

2)

        p = image(x-1, y);
        if((p == c) && (x > 0))

Вы хотели проверить, был ли он белым, как вы делали с другими направлениями?

3) Звонящий проходит черно-белым, что произойдет, если часть изображения синего цвета?Лучше было бы передать цвет заливки (черный), и там, где у вас есть белый, заменить его на не черный.

...