Python 洪水填充算法
所以我试图创建一个泛洪填充算法,我不断得到一个递归错误。该算法似乎具有无限递归性,我无法指出原因。我在互联网上到处寻找,但我找不到一个解决方案,因为根据大多数来源,我的程序似乎是正确的。然而,似乎有什么不对劲。这是代码的编辑版本。错误消息仍然是最大递归数 我能得到一些帮助吗Python 洪水填充算法,python,Python,所以我试图创建一个泛洪填充算法,我不断得到一个递归错误。该算法似乎具有无限递归性,我无法指出原因。我在互联网上到处寻找,但我找不到一个解决方案,因为根据大多数来源,我的程序似乎是正确的。然而,似乎有什么不对劲。这是代码的编辑版本。错误消息仍然是最大递归数 我能得到一些帮助吗 from Tkinter import * from PIL import Image, ImageTk from random import * w= 75 h= w
from Tkinter import *
from PIL import Image, ImageTk
from random import *
w= 75
h= w
flood = Image.new("RGB", (w,h), (0,0,0))
x = 0
y = 0
count = 0
colorlist = []
i = 0
while x < w -1:
y = 0
while y < h-1:
r = random()
if r < .25:
flood.putpixel((x,y), (0,0,0))
else:
flood.putpixel((x,y), (255,255,255))
y += 1
x += 1
x = 0
y = 0
while x < w-1:
y = 0
while y < h-1:
r = random()
if x == 0 or y == 0 or x == w-1 or y ==h-1:
flood.putpixel((x,y), (0,0,0))
y += 1
x += 1
def floodfill(x,y, d,e,f, g,h,i, image, count):
count+=1
(a,b,c) = image.getpixel((x,y))
if (a,b,c) == (255,255,255):
(j,k,l) = image.getpixel((x-1,y))
(m,n,o) = image.getpixel((x+1, y))
(p,q,r) = image.getpixel((x,y-1))
(s,t,u) = image.getpixel((x,y+1))
if count > 990:
return
if (a,b,c) == (255,255,255):
image.putpixel((x,y), (g,h,i))
floodfill(x-1, y, d,e,f, g,h,i, image, count)
floodfill(x+1, y, d,e,f, g,h,i, image, count)
floodfill(x, y-1, d,e,f, g,h,i, image, count)
floodfill(x, y+1, d,e,f, g,h,i, image,count)
floodfill(2,2, 0,0,0,255,0,0,flood, 0)
flood.save("flood.png")
print "done"
从Tkinter导入*
从PIL导入图像,ImageTk
从随机导入*
w=75
h=w
flood=图像。新(“RGB”,(w,h),(0,0,0))
x=0
y=0
计数=0
颜色列表=[]
i=0
当x990:
返回
如果(a,b,c)=(255255):
图像像素((x,y),(g,h,i))
洪水填充(x-1、y、d、e、f、g、h、i、图像、计数)
洪水填充(x+1、y、d、e、f、g、h、i、图像、计数)
洪水填充(x、y-1、d、e、f、g、h、i、图像、计数)
洪水填充(x、y+1、d、e、f、g、h、i、图像、计数)
洪水填充(2,2,0,0,0255,0,0,洪水,0)
flood.save(“flood.png”)
打印“完成”
为什么不以某种方式填充洪水,而不是递归?递归使用隐式堆栈,所以不会有任何损失
是的,正如评论中所指出的,您应该检查x和y是否超出了边界。Python有一种倾向,即抛出一个
最大递归深度超过了
的错误,即使算法不是无限递归的,最终会自行停止。有两种解决方案:增加递归限制,或切换到迭代算法
您可以使用sys.setrecursionlimit
提高递归限制。选择一个高于算法最坏情况递归深度的数字。在您的情况下,这将是图像中的像素数,length*height
将算法更改为迭代算法相当简单,因为绘制像素的顺序并不重要,只要至少获得一次。集合
非常适合保存唯一的非有序数据,因此让我们使用它来存储需要绘制的像素
def floodFill(x,y, d,e,f, g,h,i, image):
toFill = set()
toFill.add((x,y))
while not toFill.empty():
(x,y) = toFill.pop()
(a,b,c) == image.getpixel((x,y))
if not (a,b,c) == (255, 255, 255):
continue
image.putpixel((x,y), (g,h,i))
toFill.add((x-1,y))
toFill.add((x+1,y))
toFill.add((x,y-1))
toFill.add((x,y+1))
image.save("flood.png")
如果您确实使用迭代方法,请确保在其中加入边界检查。否则,它可能会永远运行!或者至少直到你的硬盘被一个巨大的
toFill
集合填满。这还没有经过测试,但主要是基于你提供的代码。它应该可以工作,并提供实现洪水填充算法的替代方法。该功能可以更有效
import PIL
import random
import collections
WHITE = 255, 255, 255
BLACK = 0, 0, 0
RED = 255, 0, 0
def main(width, height):
flood = PIL.Image.new('RGB', (width, height), BLACK)
# Create randomly generated walls
for x in range(width):
for y in range(height):
flood.putpixel((x, y), BLACK if random.random() < 0.15 else WHITE)
# Create borders
for x in range(width):
for y in range(height):
if x in {0, width - 1} or y in {0, height - 1}:
flood.putpixel((x, y), BLACK)
floodfill(50, 25, RED, image)
# Save image
image.save('flood.png')
def floodfill(x, y, color, image):
# if starting color is different from desired color
# create a queue of pixels that need to be changed
# while there are pixels that need their color changed
# change the color of the pixel to what is desired
# for each pixel surrounding the curren pixel
# if the new pixel has the same color as the starting pixel
# record that its color needs to be changed
source = image.getpixel((x, y))
if source != color:
pixels = collections.deque[(x, y)]
while pixels:
x, y = place = pixels.popleft()
image.putpixel(place, color)
for x_offset in -1, 1:
x_offset += x
for y_offset in -1, 1:
y_offset += y
new_place = x_offset, y_offset
if image.getpixel(new_place) == source:
pixels.append(new_place)
if __name__ == '__main__':
main(100, 50)
导入PIL
随机输入
导入集合
白色=255,255,255
黑色=0,0,0
红色=255,0,0
def干管(宽度、高度):
flood=PIL.Image.new('RGB',(宽度,高度),黑色)
#创建随机生成的墙
对于范围内的x(宽度):
对于范围内的y(高度):
flood.putpixel((x,y),如果为随机,则为黑色。如果为随机()<0.15,则为白色)
#创建边界
对于范围内的x(宽度):
对于范围内的y(高度):
如果{0,宽度-1}中的x或{0,高度-1}中的y:
flood.putpixel((x,y),黑色)
洪水填充(50,25,红色,图像)
#保存图像
image.save('flood.png'))
def泛光填充(x、y、颜色、图像):
#如果起始颜色与所需颜色不同
#创建需要更改的像素队列
#而有些像素需要改变颜色
#将像素的颜色更改为所需的颜色
#对于当前像素周围的每个像素
#如果新像素与起始像素具有相同的颜色
#记录其颜色需要更改
source=image.getpixel((x,y))
如果是源代码!=颜色:
像素=集合.deque[(x,y)]
而像素:
x、 y=place=pixels.popleft()
图像。像素(位置、颜色)
对于-1中的x_偏移,1:
x_偏移量+=x
对于-1中的y_偏移,1:
y_偏移量+=y
新建位置=x\U偏移,y\U偏移
如果image.getpixel(新位置)==源:
像素。追加(新位置)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
干管(100、50)
请提供您看到的确切错误消息。RuntimeError:调用Python对象时超出了最大递归深度您似乎没有检查x,y超出了界限-这可能会导致无限递归,因为x快速向左移动。或者你希望你的边界能解决这个问题?Python对递归的限制相对较低,大约1000-这是一个Python陷阱,对于那些习惯于函数语言尾部递归优化(如scheme)的人来说。好吧,我添加了一些边界,现在它没有超出边界。它适用于较小尺寸的图像,但是当您增加图像的大小时,它会增加递归的数量,从而使其达到最大值。好的,我明白了,这只是使用setrecursion的问题