如何改善我的洪水填充程序的性能?

时间:2010-12-22 07:21:38

标签: 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, 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

它有点慢,有时填充调用堆栈!而且我真的无法计算出这种算法的复杂性。

有人可以建议更好的算法来实现它吗?

5 个答案:

答案 0 :(得分:4)

当前最先进的洪水填充算法(自2006年左右)基于找到连通分量的轮廓(最外边界),将轮廓转换为水平像素运行(并检测并从连接的组件中移除内部孔),然后填充像素运行。优点是大大降低了内存需求(和/或堆栈级别)以及更快(内部像素保证只读一次并写入一次)。然而,该算法并非无足轻重。你需要阅读一些研究论文才能实现它。

答案 1 :(得分:3)

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

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

答案 2 :(得分:2)

它认为你处理的是一个图形,当我开始理解你应该改变每个节点的颜色,并且只有在目标颜色匹配时才用另一个节点替换它。

在Big O中表示的这种算法的复杂性是O(4 ^ n)所以我建议你尝试实现一个BFS算法,这样你就可以避免在没有changind的情况下留下一个未连接的节点,也避免多次传递任何顶点。这样你应该能够像O(| E | + | V |)那样| E |是边数和| V |是顶点的数量。

这是wikipedia explanation的链接,非常简单,请查看此内容!

PS:如果你需要一个有算法的人,我会非常乐意帮助你!

答案 3 :(得分:1)

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

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

在添加到队列之前,起点也应该扩展到东西两行。

编码比一次像素泛光填充要复杂一点,但通常要担心的水平线要比像素少得多。但是有一些不正常的情况。

答案 4 :(得分:0)

您可以尝试实现此例程,该例程每秒填充400万像素。

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

https://www.youtube.com/watch?v=4hQ1wA4Sl4c&feature=youtu.be

http://unity3dmc.blogspot.com/2017/02/ultimate-3d-floodfill-scanline.html?m=1