Question

J'ai un problème avec la mise en œuvre de remplissage des crues.
La tâche consiste à demander à l'utilisateur de cliquer sur la partie blanche de l'image (en indiquant le point de semences), il veut remplir avec du noir.
L'opération doit être effectuée sur les images binaires.
J'utilise la bibliothèque CImg .
I ne peut pas utilisation algorithme récursif .
Je l'ai venu avec quelque chose, mais il ne fonctionne pas correctement (l'écart devient noir que dans le point de semences). Je ne connais pas les files d'attente du tout, alors peut-être le problème est dans leur 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);
}
Était-ce utile?

La solution

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

Vous venez les x courant a sauté, coordonnées y de la pile sans regarder ce qu'ils étaient.

2)

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

Avez-vous dire pour vérifier si elle était blanche, comme vous l'avez fait avec les autres directions?

3) Les passages appelant en noir et blanc, ce qui se passe si une partie de l'image est bleu? Il serait préférable de passer à la couleur de remplissage (noir), et où vous avez blanche, remplacer par non-noir.

Autres conseils

Ne pas vous rendre compte que vous travaillez avec le même x et y tout le temps et que a.pop() ne retourne rien? std::queue::pop apparaît que l'avant de la file d'attente, mais ne retourne pas. Vous devez l'interroger au préalable en utilisant std::queue::front. Donc, il suffit d'ajouter

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

juste avant a.pop() l'intérieur de la boucle while.

Et par ailleurs, vous pouvez également définir image(x, y) (et peut-être kopia(x, y)) à c au début du bloc autre avant de pousser la paire initiale, bien qu'il puisse aussi se fixer par les itérations de ses voisins.

En outre, il y a une fonction intégrée dans CImg qui fait ce que vous voulez:. :: CImg draw_fill ()

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top