【问题标题】:Flood filling C++洪水填充 C++
【发布时间】:2011-11-30 00:02:45
【问题描述】:

我在实施洪水填充时遇到问题。
任务是让用户点击图像的白色部分(表示种子点),他想用黑色填充。
操作应该在二值图像上进行。
我正在使用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);
}

【问题讨论】:

  • 我有一个问题,您是如何使代码在编译器中看起来像的(彩色类型等)?
  • @sashafierce 在代码前放四个空格或在``中括起来或单击代码按钮以获得语法高亮。

标签: c++ cimg flooding


【解决方案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) 调用者传入黑白,如果部分图像是蓝色会怎样?最好是传入填充颜色(黑色),如果有白色,则将其替换为非黑色。

【讨论】:

  • 广告。 2) 是的,应该是 if((p == b) && (x > 0))
  • 广告。 3)我们已经指定了我们可以在这个任务中处理的图像,它们是黑白的。
  • 为了安全起见,无论如何我只会使用一种颜色。
【解决方案2】:

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

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

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

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

【讨论】:

  • 非常感谢,这很有帮助!
  • 等等,queue 弹出前面? (检查)哎呀! (修复答案)
  • 好的,几乎一切正常。我选择的飞机是填充的,但不是我想要的黑色,而是蓝色。我不知道为什么会这样。有什么建议吗?
  • 没关系,当我将黑色像素重写为 kopia 时
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-10
    • 2019-08-22
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多