Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flood fill recursive algorithm

I'm trying to make an algorithm that could fill an int array in c#. Basically, as the fill tool in MS Paint, I have a color and if I choose (x,y) coordinates in the array, it replaces all the neighbours with the same initial color with the new color.

Ex :

[0,0,0]
[0,1,0]
[1,1,0]

If I put 3 in (0,0), the array becomes :

[3,3,3]
[3,1,3]
[1,1,3]

So I tried it in recursive and it does work, but not all the time. Actually, I have sometimes a "Stack Overflow" error (seems appropriate). Here's my code, it would be great if you could tell me what's wrong :)

public int[,] fill(int[,] array, int x, int y, int initialInt, int newInt)
{
    if (array[x, y] == initialInt)
    {
        array[x, y] = newInt;

        if (x < array.GetLength(0) - 1)
            array = fill(array, (x + 1), y, initialInt, newInt);
        if (x > 0)
            array = fill(array, (x - 1), y, initialInt, newInt);

        if (y < array.GetLength(1) - 1)
            array = fill(array, x, (y + 1), initialInt, newInt);
        if (y > 0)
            array = fill(array, x, (y - 1), initialInt, newInt);
    }

    return array;
}

Thanks !

like image 824
Pimeko Avatar asked Jan 26 '14 01:01

Pimeko


People also ask

Is flood fill recursive?

Flood fill is usually implemented as a recursive algorithm which makes four recursive calls. Each recursive call tries going north, south, east, and west. To avoid infinite recursion, some method is needed to prevent repeating the same positions in the array.

Is flood fill DFS or BFS?

Floodfill can be implemented either with DFS or BFS, when all you care about is marking nodes with the same color. But when you also want to keep track of shortest distances, you'd better do a BFS rather than DFS.

What are the three flood fill techniques?

The traditional flood-fill algorithm takes three parameters: a start node, a target color, and a replacement color.

What is flood fill and boundary fill algorithm?

In Flood-fill algorithm a random colour can be used to paint the interior portion then the old one is replaced with a new one. In Boundary-fill algorithm Interior points are painted by continuously searching for the boundary colour.


2 Answers

How about using a stack/queue to manage the remaining work?

public void Fill(int[,] array, int x, int y, int newInt)
{
    int initial = array[x,y];

    Queue<Tuple<int,int>> queue = new Queue<Tuple<int,int>>();
    queue.Push(new Tuple<int, int>(x, y));

    while (queue.Any())
    {
        Tuple<int, int> point = queue.Dequeue();

        if (array[point.Value1, point.Value2] != initial)
            continue;

        array[point.Value1, point.Value2] = newInt;

        EnqueueIfMatches(array, queue, point.Value1 - 1, point.Value2, initial);
        EnqueueIfMatches(array, queue, point.Value1 + 1, point.Value2, initial);
        EnqueueIfMatches(array, queue, point.Value1, point.Value2 - 1, initial);
        EnqueueIfMatches(array, queue, point.Value1, point.Value2 + 1, initial);        
    }
}

private void EnqueueIfMatches(int[,] array, Queue<Tuple<int, int>> queue, int x, int y, int initial)
{
    if (x < 0 || x >= array.GetLength(0) || y < 0 || y >= array.GetLength(1))
        return;

    if (array[x, y] == initial)
       queue.Enqueue(new Tuple<int, int>(x, y));
}
like image 177
Scott Wegner Avatar answered Oct 11 '22 19:10

Scott Wegner


This is a textbook example of why using recursion is not always appropriate. Recursion is great for going through data structures that are inherently recursive (e.g. trees), but your array of pixel data is not.

I suggest to add a counter to your code to print how often the fill() function is called. On every function call, your machine has to create a new frame on the stack in memory (so it knows to which memory position it has to return after the function is over). The recursive image fill algorithm calls the fill() function a huge number of times, hence the stack will grow very quickly. It has a limited size, so it will overflow for larger pictures.

The solution is to implement an iterative fill algorithm, using loops instead of recursion to iterate over the pixels.

See Wikipedia on recursion and stack overflows, or “Computer Graphics, Principles and Practice” by Foley et al. for a more detailed introduction to basic computer graphics algorithms.

like image 38
Leon Weber Avatar answered Oct 11 '22 20:10

Leon Weber