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的问题