洪水充填C++
我在实施洪水填充时遇到问题。
任务是要求用户点击图像的白色部分(表示种子点),他想要用黑色填充。
该操作应该在二值图像上完成。
我正在使用 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);
}
I have a problem with implementation of flood filling.
The task is to ask user to click on the white part of the image (indicating seed point), he want to fill with black.
The operation should be done on the binary images.
I'm using CImg library.
I can't use recursive algorithm.
I've came up with something but it is not working properly (the gap becomes black only in the seed point). I am not familiar with the queues at all, so maybe the problem is in their 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);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
1)
你只是将当前的 x,y 坐标从堆栈中弹出,而没有查看它们是什么。
2)
你的意思是检查它是否是白色的,就像你对其他方向所做的那样?
3)调用者传入黑白图像,如果图像的一部分是蓝色会发生什么?更好的方法是传递填充颜色(黑色),只要有白色,就用非黑色替换它。
1)
You just popped the current x,y coordinates off the stack without looking at what they were.
2)
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.
您是否意识到您始终使用相同的
x
和y
并且a.pop()
不会返回任何事物?std::queue::pop
仅弹出队列的前端,但不返回它。您必须事先使用std::queue::front
查询它。 添加因此,只需在 while 循环内的
a.pop()
之前即可。顺便说一句,您可能还想将
image(x, y)
(也许还有kopia(x, y)
)设置为c
在推送初始对之前,在 else 块的开头,尽管它也可能由其邻居的迭代设置。Don't you realize that you are working with the same
x
andy
all the time and thata.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 usingstd::queue::front
. So just addright before
a.pop()
inside the while loop.And by the way, you might also want to set
image(x, y)
(and maybekopia(x, y)
) toc
at the beginning of the else block before pushing the initial pair, although it might also get set by its neighbours' iterations.此外,CImg 中有一个内置函数可以完成您想要的操作:CImg::draw_fill()。
Also, there is a built-in function in CImg that does what you want : CImg::draw_fill().