算法,洪水填充(深度优先搜索)

我正在使用Java。
我正在开发一个绘图程序,“Paint Can”工具正在使用Flood Fill算法,但它太贵了。

这是代码:

private int[] dx = { -1, 0, 1, 0 }; private int[] dy = { 0, 1, 0, -1 }; public void floodFill(int x, int y, Color target_color, Color replacement_color) { Stack stack = new Stack(); if (imageBuffer.getRGB(x, y) == replacement_color.getRGB()) return; stack.push(new Integer[] { x, y }); while (!stack.isEmpty()) { Integer[] aux = stack.peek(); imageBuffer.setRGB(aux[0], aux[1], replacement_color.getRGB()); stack.pop(); for (int i = 0; i < 4; i++) { if (imageBuffer.getRGB(aux[0] + dx[i], aux[1] + dy[i]) == target_color.getRGB()) stack.push(new Integer[] { aux[0] + dx[i], aux[1] + dy[i] }); } } } 

有人能帮助我提高效率吗?

它需要(对于1020×700像素图像)大约1200ms才能执行。

使用队列算法的基本思路,你可以在这里阅读(+示例)。

您可以找到其他优化和实现,但我发现这是一个Queue-Linear Flood Fill 。 你应该自己完成这项工作。

一个快速简单(可能很小)的改进是用ArrayDeque替换Stack。

这将允许您指定初始容量并使您的代码更新。 当floodFill区域包含许多像素时,需要扩展多次向下扩展的Vector。 这很浪费 – 但并不是那么昂贵

大约一年前,我曾试图实施一个泛洪算法。 我首先尝试了自己的解决方案,当他们不够高效时,我去了互联网并找到了这个实现 。

QuickFill (实际算法从页面的一半开始)算法运行良好。 它将在不到半秒的时间内填满我的机器人里程碑屏幕(480×854)。 使用更新的硬件(甚至桌面硬件),它可能会比这更快。 当然你必须把它移植到Java,但它不应该太难,特别是如果我能做到的话!

我会说你有很多内存分配正在进行中。 您为每个像素分配一个新的Integer[] 。 我可能会使用两堆基元(比如, trove4j中的数组列表),要处理xy ,或者至少用int[]替换Integer[] int[]

如果这还不够,也许扫描线算法会有所帮助。