0

I have a problem with working of my automata - Game of Life. Well, I have an image which I convert to the 2d matrix. On the middle of this image there is an oscilator. As the rules say, the output of this function should be another oscilator but turned by 90 degrees. Unfortunately my output is wrong. You can see on the images below. What's wrong with the code? Could you help me with solving this problem?

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

Edit: I'm adding more functions, maybe there is a problem. Now my code looks like this:

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

That's ORIGINAL 50x50 input and output. original input original output

D4wid3k
  • 17
  • 3
  • Yes, I've thought about it for long time, but I have no idea how to not mixing up present and future. Something is wrong with the matrix saving, but what? – D4wid3k Nov 08 '20 at 22:49

3 Answers3

2

You're taking y values % tab_x instead of % tab_y.

And in this bit

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

you're missing some cases. Remember, you initialized new_tab to zeroes, so you never need to set a 0, but you do need to set a 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

should work.

Finally, in your readout loop, you're indexing the array by [y, x] instead of [x, y].

hobbs
  • 223,387
  • 19
  • 210
  • 288
  • That's no problem in it, because for the example tab_x and tab_y are the same. – D4wid3k Nov 08 '20 at 22:25
  • Your updated code doesn't solve my problem. :( I think there's a problem with saving my matrix. Something gone wrong there, but I have no idea how to fix it. – D4wid3k Nov 08 '20 at 22:51
0

I notice that you seem to be reading and writing your images in the JPEG format, and that your image reading code treats every pixel that isn't pure white (255) as a live cell.

JPEG is a lossily compressed image format, which means that the pixel values you get back from reading an image file typically won't be exactly the same as what you wrote into the file. In particular, when the original image contains sharp boundaries between highly contrasting colors, there will typically be fringing and other compression artifacts near those boundaries in the JPEG compressed version. When parsed by your code, this fringing will cause additional live cells to appear near your patterns.

(To confirm that this is an issue, try removing the CA simulation code entirely and just copying the cell states from tab to new_tab unchanged. Your output image probably won't match the input.)

If you insist on using the JPEG format, you should change the if tab[x, y] == 255 condition in your image reading code to something more robust like if tab[x, y] > 127. You should also strongly consider using a different image format, such as PNG, for this purpose.

Ps. As a general tip, you could've figured this issue out yourself if you'd tested your code with very small images (say, 8 by 8 pixels or smaller) and either printed out the contents of your tab / new_tab arrays at various points in your code or, better yet, stepped through your code in a debugger and used it to examine the arrays.

Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153
0

On top of what hobbs said regarding the ranges, you forgot the case where the cell survives. You only covered what happens when it dies or when a new one is born.

This is only because we start with an empty new_tab = np.zeroslike(tab). If we started with new_tab = tab.copy we wouldn't have to specify that the cell survived.

I made a matplotlib solution to show you the animated result :)

enter image description here

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
Guimoute
  • 4,407
  • 3
  • 12
  • 28
  • I've made your suggestions, but problem still exists. I don't know what's wrong. I'll post here another functions that are connected with this one, maybe problem is in different place. – D4wid3k Nov 09 '20 at 10:30