我正在尝试实现类似洪泛的算法。问题是我不知道我应该以什么方式实现它,例如递归 - 非递归 我知道每个都有缺陷,但其中一个必须比另一个快。当非递归每次分配4个新点时,递归在堆栈上打开新函数 非迭代的例子:
Stack<Point> stack = new Stack<Point>();
stack.Push(q);
while (stack.Count > 0)
{
Point p = stack.Pop();
int x = p.X;
int y = p.Y;
if (y < 0 || y > h - 1 || x < 0 || x > w - 1)
continue;
byte val = vals[y, x];
if (val == SEED_COLOR)
{
vals[y, x] = COLOR;
stack.Push(new Point(x + 1, y));
stack.Push(new Point(x - 1, y));
stack.Push(new Point(x, y + 1));
stack.Push(new Point(x, y - 1));
}
}
编辑:我将在600X600像素的地图上应用以下算法。尽管洪水填充不会应用于整个地图,但每次迭代它应覆盖约30%-80%的地图。我的观点是发现高度图中的边缘并标记这些边缘以供进一步使用。
答案 0 :(得分:2)
this似乎是我发现的洪水填充最有效的实现......
我提到this answer中提到的边界填充技术是一个很好的技术,但不如quickfill好。
答案 1 :(得分:1)
制作一个掩码 - 一个平行的2-dim字节数组。未经检查的区域字节为0,对于洪水区域的新鲜边界,它将具有值1.对于洪水区域的内部 - 值2.并保留当前边界点的列表。
在外循环的任何一端,您都有具有标记的当前边界,内部和外部区域以及边界点阵列的蒙版。因此,您将仅在边框上检查新点。在检查边界点的第一个arraylist时,您正在创建第二个边框arraylist和第二个mask。在下一步中,您将重新创建第一个边框数组和蒙版。这样,我们可以使用简单的while
循环而不是递归,因为您在任何步骤检查的数据结构都非常简单。
至于在所有相邻点骑行,请查看我的算法here
答案 2 :(得分:0)
如果图像很复杂,递归填充可能会溢出堆栈。使用非递归填充。
如果您关心分配,可以将一个点表示为long类型的打包值,并编写自己的LongStack,在内部将long值存储在数组中。
答案 3 :(得分:0)
计算机非常高效地处理XY循环和2D阵列。
如果您可以使用XY循环和2D数组扫描泛洪,而不是使用各种逐步逻辑,则可能会很快。
最简单的逐步逻辑是泛洪递归函数,该函数仅检查4个邻居。这就是我过去在2017 i7处理器上实现每秒900万像素的原因。这是一段解释逻辑简单性的视频。它使用2D数组而不是内存(非常有效)并循环: https://www.youtube.com/watch?v=Xddws-50Igs
这是一个带有视频的页面,该视频证明我在2012 FX处理器上以这种算法每秒获得400万个体素。(7秒钟内填充了3300万个体素) https://unity3dmc.blogspot.com/2017/02/ultimate-3d-floodfill-scanline.html?showComment=1537614917045#c9221615743847221048