Наполнение наводнения 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);
}
Решение
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) Звонящий проходит в черно -белом, что произойдет, если часть изображения синяя? Лучше было бы пройти в цвете начинки (черный), и где бы вы ни были белые, замените его не черным.
Другие советы
Разве вы не понимаете, что работаете с тем же x
а также y
все время и это a.pop()
ничего не возвращает? std::queue::pop
Только выскакивает переднюю часть очереди, но не возвращает ее. Вы должны запросить его заранее, используя std::queue::front
. Анкет Так что просто добавьте
x = a.front().first;
y = a.front().second;
прямо перед a.pop()
внутри петли.
И, кстати, вы также можете захотеть установить image(x, y)
(и возможно kopia(x, y)
) к c
В начале блока Else, прежде чем выдвигать начальную пару, хотя он также может быть установлен итерациями своих соседей.
Кроме того, в CIMG существует встроенная функция, которая делает то, что вы хотите: cimg :: draw_fill ().