Algorithm 如何提高洪水填充例程的性能?

Algorithm 如何提高洪水填充例程的性能?,algorithm,pseudocode,Algorithm,Pseudocode,我正在我的应用程序中实现四路洪水填充,下面给出了伪代码 Flood-fill (node, target-color, replacement-color): 1. If the color of node is not equal to target-color, return. 2. Set the color of node to replacement-color. 3. Perform Flood-fill (one step to the west of node, targe

我正在我的应用程序中实现四路洪水填充,下面给出了伪代码

Flood-fill (node, target-color, replacement-color):
 1. If the color of node is not equal to target-color, return.
 2. Set the color of node to replacement-color.
 3. Perform Flood-fill (one step to the west of node, target-color, replacement-color).
    Perform Flood-fill (one step to the east of node, target-color, replacement-color).
    Perform Flood-fill (one step to the north of node, target-color, replacement-color).
    Perform Flood-fill (one step to the south of node, target-color, replacement-color).
 4. Return
它有点慢,有时会填满调用堆栈!我真的无法计算这个算法的复杂度

有谁能推荐更好的算法来实现它吗?

我不能用C帮助你,因为我只在Delphi中做过,但我可以帮助你解决调用堆栈问题。诀窍是不要使用递归算法。相反,通过维护需要检查的点的堆栈,使用基于堆栈的方法


基本上,将“起点”添加到堆栈中(并更改其颜色)。然后,当堆栈不为空时,从堆栈中取出最后一点(即,弹出它)。对所有4个方向(左、右、上、下)进行比较。如果任何相邻像素需要翻转为新颜色,请进行翻转,然后将该相邻点添加到堆栈中。在下一个循环中,堆栈上应该有更多的点。继续循环,直到堆栈为空

通过使用较大的项目(水平线而不是单个像素),可以减少堆栈上通常需要的项目数量

每次从堆栈/队列中获取一条线时,将该线的全长扫描一个北像素和一个南像素,以形成许多附加的水平线,添加到堆栈中。这些线中最东和最西的线可能会比原始线的边界向东/向西延伸得更远,所以要这样做。然后将所有这些附加行添加到堆栈/队列

在将起点添加到队列之前,还应将起点延伸到东、西两条线


编码将比一次一个像素的整体填充稍微复杂一些,但通常需要担心的水平线要比像素少得多。不过,也有一些不合理的情况。

它认为您处理的是一个图形,当我谈到uderstand时,您应该更改每个节点的颜色,并且只有在目标颜色匹配时才用另一个节点替换它

这个用大O表示的算法的复杂度是O(4^n),所以我建议您尝试实现BFS算法,这样您可以避免在没有更改的情况下离开一个未连接的节点,也可以避免在任何垂直上传递多次。这样,您应该能够在O(| E |+| V |)中执行,其中| E |是边的数量| V |是顶点的数量

这是一个链接,非常简单,所以请查看


附言:如果你需要一个与算法,我会非常乐意帮助你

当前最先进的泛光填充算法(自2006年左右以来)基于找到连接组件的轮廓(最外边界),将轮廓转换为水平像素运行(并检测和移除连接组件的内部孔),然后填充像素运行。其好处是大大降低了内存需求(和/或堆栈级别)和速度(保证内部像素只读取一次,写入一次)。然而,该算法并不简单。你需要阅读一些研究论文才能实现它。

你可以尝试实现这个例程,它每秒填充400万像素

在2017年推出的I7上,这相当于每秒900万个泛洪像素,因此可以使用10-15MB内存在大约0.1秒内处理1024x1024像素的图像:


@Manoj-你的观点是什么?虽然这个问题涉及洪水的填充,但这不是一个dup。无论如何。这个问题不是关于如何实施洪水填充,而是关于如何建立一个最优的策略来应用多个洪水填充来实现一个目标,这是完全不同的。只是帮助那个家伙。我觉得这不属于这里。“这是一个很重要的问题。”Prashant——每个人都说这个问题属于StackOverflow。它最终会在这个网站上关闭。这是一个很好的观点。处理器堆栈可能是相当有限的资源-在大多数系统上,您不能将整个系统内存(或任何远程接近的内存)用作CPU堆栈。在堆上管理的堆栈数据结构通常会在出现问题之前变得更大。谢谢@Steve314。这听起来比我做的更好,但是,我想这将是相当困难的代码。这是正确的。水平或垂直运行更有效。但是,一旦将有界区域减少为一组3点多边形,就不太困难了。3点多边形不会有洞,它们的运行可以进一步优化。@rwong:我对这个主题感兴趣,但没有找到关于这个轮廓跟踪方法的参考资料。如果可能的话,你有更多的建议来指导我吗?@YvesDaoust:我没有足够的知识来提供建议。(此外,轮廓跟踪不再是最先进的技术,因为它不在GPU上运行。)我的建议是改为参考,因为询问者已经发布了各种方法的非常全面的列表(以及陷阱)。@rwong:感谢您快速回答。我特别感兴趣的是你在回答中提到的内容;我知道你读了2006年左右发表的一些文章;这可能是“Chang&Chen提出的采用轮廓跟踪技术的元件标记算法”吗?如果是的话,这是关于连通成分分析的最好的论文之一,但不是我想要的:我想从给定的内部像素填充一个斑点,而不是找到图像中的所有斑点。(同样在我的上下文中,GPU是不相关的。)或者它可能是“一种新的快速轮廓填充算法,Ren&Yang”?复杂性不应该是O(n^2)吗?我认为它也是O(4^n),但由于n是矩阵的最大尺寸,它不可能穿越矩阵中更多的空间。如果复杂性是O(4^n),地球上很少有洪水填充引擎能够在典型区域完成任务。F.i.,4^100=1