Frage

Ich habe ein Problem mit der Implementierung von Überschwemmungsfüllung.
Die Aufgabe besteht darin, den Benutzer aufzufordern, auf den weißen Teil des Bildes zu klicken (Saatgutpunkt anzeigt), er möchte mit Schwarz füllen.
Die Operation sollte auf den binären Bildern durchgeführt werden.
Ich benutze Cimg Bibliothek.
ich kippen verwenden rekursiv Algorithmus.
Ich habe mir etwas ausgedacht, aber es funktioniert nicht richtig (die Lücke wird nur im Samenpunkt schwarz). Ich bin mit den Warteschlangen überhaupt nicht vertraut, also liegt das Problem vielleicht in ihrer Implementierung.

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);
}
War es hilfreich?

Lösung

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

Sie haben gerade das aktuelle X, Y, vom Stapel koordiniert, ohne sich anzuschauen, was sie waren.

2)

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

Wolltest du prüfen, ob es weiß war, wie du es in den anderen Anweisungen getan hast?

3) Der Anrufer geht in Schwarz und Weiß vorbei. Was passiert, wenn ein Teil des Bildes blau ist? Besser wäre es, die Füllfarbe (schwarz) in die Füllfarbe einzugeben, und wo immer Sie Weiß haben, ersetzen Sie das durch nicht schwarze.

Andere Tipps

Merken Sie nicht, dass Sie mit demselben arbeiten x und y die ganze Zeit und das a.pop() Gibt nichts zurück? std::queue::pop Popt nur die Vorderseite der Warteschlange, gibt sie aber nicht zurück. Sie müssen es im Voraus verwenden std::queue::front. Also einfach hinzufügen

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

kurz bevor a.pop() Innerhalb der while Schleife.

Übrigens möchten Sie auch einstellen image(x, y) (und vielleicht kopia(x, y)) zu c Zu Beginn des elendlichen Blocks vor dem Drücken des ersten Paares, obwohl es auch von den Iterationen seiner Nachbarn festgelegt wird.

Außerdem gibt es eine integrierte Funktion in CIMG, die das tut, was Sie wollen: cimg :: draw_fill ().

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top