3

我对洪水填充的实施有疑问。
任务是要求用户点击图像的白色部分(表示种子点),他想用黑色填充。
该操作应在二进制图像上完成。
我正在使用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);
}
4

3 回答 3

1

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)调用者传入黑白,如果部分图像是蓝色的会怎样?最好是传入填充颜色(黑色),无论你有白色,用非黑色替换它。

于 2011-11-30T00:15:50.960 回答
1

难道你没有意识到你一直在使用相同x的东西y并且a.pop()没有任何回报吗?std::queue::pop只弹出队列的前面,但不返回它。您必须事先使用std::queue::front. 所以只需添加

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

就在a.pop()while循环之前。

顺便说一句,您可能还希望在推送初始对之前在 else 块的开头设置image(x, y)(并且可能kopia(x, y))设置为,尽管它也可能被其邻居的迭代设置。c

于 2011-11-30T00:18:26.143 回答
1

此外,CImg 中有一个内置函数可以满足您的需求:CImg::draw_fill()。

于 2011-11-30T08:26:13.563 回答