Domanda

Ho un problema con l'implementazione di di riempimento diluvio.
Il compito è quello di chiedere all'utente di cliccare sulla parte bianca dell'immagine (che indica il punto di semi), egli desidera riempire con il nero.
L'operazione deve essere eseguita sulle immagini binarie.
Sto utilizzando CImg biblioteca.
I non possono utilizzo ricorsiva algoritmo.
ho si avvicinò con qualcosa, ma non funziona correttamente (il divario diventa nero solo nel punto seme). Non ho familiarità con le code a tutti, quindi forse il problema è nel loro implementaion.

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);
}
È stato utile?

Soluzione

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();

You just popped the current x,y coordinates off the stack without looking at what they were.

2)

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

Did you mean to check if it was white, like you did with the other directions?

3) The caller passes in black and white, what happens if part of the image is blue? Better would be to pass in the filling color (black), and wherever you have white, replace that with not-black.

Altri suggerimenti

Don't you realize that you are working with the same x and y all the time and that a.pop() doesn't return anything? std::queue::pop only pops the front of the queue, but doesn't return it. You have to query it beforehand using std::queue::front. So just add

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

right before a.pop() inside the while loop.

And by the way, you might also want to set image(x, y) (and maybe kopia(x, y)) to c at the beginning of the else block before pushing the initial pair, although it might also get set by its neighbours' iterations.

Also, there is a built-in function in CImg that does what you want : CImg::draw_fill().

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top