生命游戏实施在 Python 中无法正常运行

Game of Life implementation doesn't work properly in Python

我在使用我的自动机 - 生命游戏时遇到问题。好吧,我有一张图像,我将其转换为二维矩阵。在这张图片的中间有一个振荡器。正如规则所说,此函数的输出应该是另一个振荡器,但旋转了 90 度。不幸的是我的输出是错误的。你可以在下面的图片上看到。代码有什么问题?你能帮我解决这个问题吗?

def sim():
    tab = cv2.imread(jpg_path, 0)
    tab_x = tab.shape[0]
    tab_y = tab.shape[1]

    new_tab = np.zeros([tab_x, tab_y])

    for x in range(0, tab_x):
        for y in range(0, tab_y):
            if tab[x, y] == 255:
                tab[x, y] = 0
            else:
                tab[x, y] = 1

    #new_tab = tab.copy()

    for x in range(tab_x):
        for y in range(tab_y):
     
            summary = (tab[x, (y-1) % tab_x] + tab[x, (y+1) % tab_x] +
                         tab[(x-1) % tab_x, y] + tab[(x+1) % tab_x, y] +
                         tab[(x-1) % tab_x, (y-1) % tab_x] + tab[(x-1) % tab_x, (y+1) % tab_x] +
                         tab[(x+1) % tab_x, (y-1) % tab_x] + tab[(x+1) % tab_x, (y+1) % tab_x])

            if tab[x, y] == 1:
                if (summary < 2) or (summary > 3):
                    new_tab[x, y] = 0
            else:
                if summary == 3:
                    new_tab[x, y] = 1

    for y in range(0, tab_y):
        for x in range(0, tab_x):
            if new_tab[y, x] == 1:
                new_tab[y, x] = 0
            else:
                new_tab[y, x] = 255

    cv2.imwrite('anMD.jpg', new_tab)

input output

编辑:我正在添加更多功能,可能有问题。现在我的代码如下所示:

def osc(tab, x, y):
    tab[x-1,y-1] = 0
    tab[x-1,y] = 1
    tab[x-1,y+1] = 0
    tab[x,y-1] = 0
    tab[x,y] = 1
    tab[x,y+1] = 0
    tab[x+1,y-1] = 0
    tab[x+1,y] = 1
    tab[x+1,y+1] = 0

    return tab

def gol():
    tab_x = 50
    tab_y = 50

    x = 25
    y = 25

    tab = np.zeros([tab_x, tab_y])
    new_tab = osc(tab, x, y)

    for y in range(0, tab_y):
        for x in range(0, tab_x):
            if new_tab[y, x] == 1:
                new_tab[y, x] = 0
            else:
                new_tab[y, x] = 255

    cv2.imwrite('anMD.jpg', new_tab)
    canvas.delete("all")
    cv2.imwrite('show.jpg', new_tab)
    image = Image.open('show.jpg')
    new_image = image.resize((500, 500))
    new_image.save('show.jpg')
    dimg = ImageTk.PhotoImage(Image.open('show.jpg'))
    canvas.create_image(0, 0, anchor='nw', image=dimg)
    canvas.image = dimg

def sim():
    tab = cv2.imread(jpg_path, 0)
    tab_x = tab.shape[0]
    tab_y = tab.shape[1]

    new_tab = np.zeros_like(tab)

    for x in range(0, tab_x):
        for y in range(0, tab_y):
            if tab[x, y] == 255:
                tab[x, y] = 0
            else:
                tab[x, y] = 1

    for x in range(tab_x):
        for y in range(tab_y):
            """summary = 0
            summary += tab[x - 1, y - 1]
            summary += tab[x - 1, y]
            summary += tab[x - 1, y + 1]
            summary += tab[x, y - 1]
            summary += tab[x, y + 1]
            summary += tab[x + 1, y - 1]
            summary += tab[x + 1, y]
            summary += tab[x + 1, y + 1]"""

            summary = (tab[x, (y-1) % tab_y] + tab[x, (y+1) % tab_y] +
                         tab[(x-1) % tab_x, y] + tab[(x+1) % tab_x, y] +
                         tab[(x-1) % tab_x, (y-1) % tab_y] + tab[(x-1) % tab_x, (y+1) % tab_y] +
                         tab[(x+1) % tab_x, (y-1) % tab_y] + tab[(x+1) % tab_x, (y+1) % tab_y])

            if tab[x, y] == 1:
                if (summary < 2) or (summary > 3):
                    new_tab[x, y] = 0
                else:
                    new_tab[x, y] = 1
            else:
                if summary == 3:
                    new_tab[x, y] = 1

    for y in range(0, tab_y):
        for x in range(0, tab_x):
            if new_tab[y, x] == 1:
                new_tab[y, x] = 0
            else:
                new_tab[y, x] = 255

    for x in range (tab_x):
        for y in range (tab_y):
            tab[x, y] = new_tab[x, y]

    cv2.imwrite('anMD.jpg', new_tab)
    cv2.imwrite('show.jpg', new_tab)
    image = Image.open('show.jpg')
    new_image = image.resize((500,500))
    new_image.save('show.jpg')
    canvas.delete("all")
    dimg = ImageTk.PhotoImage(Image.open('show.jpg'))
    canvas.create_image(0, 0, anchor='nw', image=dimg)
    canvas.image = dimg

这是原始的 50x50 输入和输出。 original input original output

您正在使用 y 值 % tab_x 而不是 % tab_y

而在这一点

if tab[x, y] == 1:
    if (summary < 2) or (summary > 3):
        new_tab[x, y] = 0
    else:
        if summary == 3:
            new_tab[x, y] = 1

您遗漏了一些案例。请记住,您将 new_tab 初始化为零,因此您永远不需要设置 0,但是 需要设置 1。

if tab[x, y] == 1:
    if (summary == 2) or (summary == 3):
        new_tab[x, y] = 1
else:
    if summary == 3:
        new_tab[x, y] = 1

应该可以。

最后,在您的读出循环中,您通过 [y, x] 而不是 [x, y] 对数组进行索引。

我注意到您似乎正在以 JPEG 格式读写图像,并且您的图像读取代码将每个非纯白色 (255) 的像素都视为活细胞。

JPEG 是一种有损压缩的图像格式,这意味着您从读取图像文件中获得的像素值通常不会与您写入文件的像素值完全相同。特别是,当原始图像包含高对比度颜色之间的清晰边界时,在 JPEG 压缩版本中这些边界附近通常会有 fringing and other compression artifacts。当您的代码解析时,此边缘会导致其他活细胞出现在您的图案附近。

(要确认这是一个问题,请尝试完全删除 CA 模拟代码并仅将单元状态从 tab 复制到 new_tab 不变。您的输出图像可能与输入。)

如果您坚持使用 JPEG 格式,则应将图像读取代码中的 if tab[x, y] == 255 条件更改为更强大的条件,例如 if tab[x, y] > 127。为此,您还应该强烈考虑使用不同的图像格式,例如 PNG。

Ps。作为一般提示,如果您使用非常小的图像(例如 8 x 8 像素或更小)测试代码并打印出 tab / new_tab 数组在你的代码中的不同点,或者更好的是,在 debugger 中单步执行你的代码并用它来检查数组。

除了hobbs所说的范围之外,您还忘记了细胞存活的情况。您只介绍了它死去或新的出生时发生的事情。

这只是因为我们从一个空 new_tab = np.zeroslike(tab) 开始。如果我们从 new_tab = tab.copy 开始,我们就不必指定细胞存活。

我制作了一个 matplotlib 解决方案来向您展示动画结果:)

import numpy as np
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
fig.show()

# Base data.
tab = np.zeros((10, 10))
tab[4, 2] = 1
tab[4, 3] = 1
tab[4, 4] = 1

ax.imshow(tab)
ax.set_title("0")
plt.pause(0.3)

# Play 10 turns.
for n in range(10):
    new_tab = np.zeros_like(tab)
    tab_x, tab_y = tab.shape

    for x in range(tab_x):
        for y in range(tab_y):

            summary = (  tab[x, (y-1) % tab_y]
                       + tab[x, (y+1) % tab_y]
                       + tab[(x-1) % tab_x, y]
                       + tab[(x+1) % tab_x, y]
                       + tab[(x-1) % tab_x, (y-1) % tab_y]
                       + tab[(x-1) % tab_x, (y+1) % tab_y]
                       + tab[(x+1) % tab_x, (y-1) % tab_y]
                       + tab[(x+1) % tab_x, (y+1) % tab_y])

            if tab[x, y] == 1:
                if (summary < 2) or (summary > 3):
                    new_tab[x, y] = 0
                else:
                    new_tab[x, y] = 1 # Survival case you need to add to your code.
            else:
                if summary == 3:
                    new_tab[x, y] = 1

    ax.imshow(new_tab)
    ax.set_title(f"{n+1}")
    plt.pause(0.3)

    tab = new_tab