洪水中的Stackoverflow错误

时间:2014-01-04 16:22:36

标签: c# image bitmap stack-overflow flood-fill

我正在尝试在连接的二进制图像区域上实现泛洪填充,但是我得到了StackOverflow错误。此外,我如何为每个区域着色不同的颜色。

由于

public  void FloodFill(int x, int y)
{
    Bitmap bitmap = (Bitmap)pictureBox1.Image;

    if ((x < 0) || (y < 0) || (x >= bitmap.Width) || (y >= bitmap.Height)) { return; }

    Color cl = bitmap.GetPixel(x, y); // error An unhandled exception of type 'System.StackOverflowException' occurred in System.Drawing.dll

    if ((cl.R != 255) || (cl.G != 255) || (cl.B != 255)) { return; }
    if ((cl.R == 255) && (cl.G == 255) && (cl.B == 255)) {
        bitmap.SetPixel(x, y, Color.FromArgb(255, 255, 0, 0));
    }
    FloodFill(x, y - 1);
    FloodFill(x + 1, y - 1);
    FloodFill(x + 1, y);
    FloodFill(x + 1, y + 1);
    FloodFill(x, y + 1);
    FloodFill(x - 1, y + 1);
    FloodFill(x - 1, y);
    FloodFill(x - 1, y - 1);
}
for (int i = 0; i < pictureBox1.Width; i++)
{
    for (int j = 0; j < pictureBox1.Height; j++) {
        Point p = new Point(i, j);
        FloodFill(p.X, p.Y);
    }
}

2 个答案:

答案 0 :(得分:4)

PMF是正确的;你应该使用迭代算法。

迭代算法是:

Fill(coordinate)
    stack = new Stack<Coordinate>()
    stack.Push(coordinate)
    while !stack.IsEmpty
        current = stack.Pop();
        if bitmap[current] is not white then continue
        bitmap[current] = black
        stack.Push(current.NorthNeighbour)            
        stack.Push(current.SouthNeighbour)
        etc.

你看到它是如何工作的吗?我们的想法是,不是使用调用堆栈作为临时存储,而是实际分配自己的堆栈。

答案 1 :(得分:3)

我猜这个问题与递归的顺序有关。在最坏的情况下,你(几乎)将首先处理整个图像深度。递归可能与图像中的总像素一样深。

让我们假设我们从10x10图像的左下角开始。前几步是:

  • 我们递归地输入第一个FloodFill(x,y-1),直到y = 0 =&gt;堆叠深度10
  • 回溯一步,接下来我们可以做的就是FloodFill(x + 1,y)直到x = 9,y = 0 =&gt;堆栈深度19
  • 再次回溯,接下来我们做的是FloodFill(x-1,y)直到x = 1,y = 0 =&gt;堆叠深度27
  • 现在我们第一次需要在堆栈中超过一个级别。

所以你需要一个至少2 *宽+ 2 *图像高度的堆栈大小 - 以上只是一个快速分析。这可能会有很多。

建议:使用迭代算法。