算法,洪水填充(深度优先搜索)
我正在使用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中的数组列表),要处理x
和y
,或者至少用int[]
替换Integer[]
int[]
。
如果这还不够,也许扫描线算法会有所帮助。