生命游戏是英国数学家约翰·何顿·康威在1970年发明的细胞自动机,它包括一个二维矩形世界,这个世界中的每个方格居住着一个活着的或死亡的细胞。一个细胞在下一个时刻生死取决于相邻八个方格中活着的或死了的细胞的数量。如果相邻方格活着的细胞数量过多,这个细胞会因为资源匮乏而在下一个时刻死去;相反,如果周围活细胞过少,这个细胞会因太孤单而死去。
游戏在一个类似于围棋棋盘一样的,可以无限延伸的二维方格网中进行。例如,设想每个方格中都可放置一个生命细胞,生命细胞只有两种状态:“生”或“死”。图中,用黑色的方格表示该细胞为“死”, 其它颜色表示该细胞为“生”。游戏开始时, 每个细胞可以随机地(或给定地)被设定为“生”或“死”之一的某个状态, 然后,再根据如下生存定律计算下一代每个细胞的状态:
-
每个细胞的状态由该细胞及周围8个细胞上一次的状态所决定;
-
如果一个细胞周围有3个细胞为生,则该细胞为生,即该细胞若原先为死则转为生,若原先为生则保持不变;
-
如果一个细胞周围有2个细胞为生,则该细胞的生死状态保持不变;
-
在其它情况下,该细胞为死,即该细胞若原先为生则转为死,若原先为死则保持不变。
网上有的代码自己跑不出来可视化的,自己写了一个。
import numpy as np import matplotlib.pyplot as plt from matplotlib import animation import cv2 img = np.random.randint(2, size=(3, 3)) max_alive = 3 num_alive = 2 def wise_element_sum(img, fil): return (img * fil).sum() # calculate convolution 1 def convolve(img): fil_lt = np.array([[0, 1], [1, 1]]) fil_t = np.array([[1, 0, 1], [1, 1, 1]]) fil_rt = np.array([[1, 0], [1, 1]]) fil_l = np.array([[1, 1], [0, 1], [1, 1]]) fil_r = np.array([[1, 1], [1, 0], [1, 1]]) fil_ld = np.array([[1, 1], [0, 1]]) fil_d = np.array([[1, 1, 1], [1, 0, 1]]) fil_rd = np.array([[1, 1], [1, 0]]) fil_o = np.array([[1, 1, 1], [1, 0, 1], [1, 1, 1]]) conv_height = img.shape[0] conv_weight = img.shape[1] conv = np.zeros((conv_height, conv_weight), dtype='uint8') for i in range(conv_height): if i == 0: for j in range(conv_weight): if j == 0: # the left top point conv[i][j] = wise_element_sum(img[i: fil_lt.shape[0], j: fil_lt.shape[1]], fil_lt) elif j == conv_weight - 1: # the right top point conv[i][j] = wise_element_sum(img[i: fil_lt.shape[0], j - 1: j + 1], fil_rt) else: # the top row conv[i][j] = wise_element_sum(img[i: fil_lt.shape[0], j - 1: j + 2], fil_t) elif i == conv_height - 1: for j in range(conv_weight): if j == 0: # the left bottom point conv[i][j] = wise_element_sum(img[i - 1: conv_height, j: fil_ld.shape[1]], fil_ld) elif j == conv_weight - 1: # the right bottom point conv[i][j] = wise_element_sum(img[i - 1: conv_height, j - 1: j + 1], fil_rd) else: # the bottom raw conv[i][j] = wise_element_sum(img[i - 1: conv_height, j - 1: j + 2], fil_d) else: for j in range(conv_weight): if j == 0: # the left column conv[i][j] = wise_element_sum(img[i - 1: i + 2, j: fil_ld.shape[1]], fil_l) elif j == conv_weight - 1: # the right column conv[i][j] = wise_element_sum(img[i - 1: i + 2, j - 1: j + 1], fil_r) else: # the center/others point conv[i][j] = wise_element_sum(img[i - 1: i + 2, j - 1: j + 2], fil_o) return conv # format the result of convolution def format_conv(img): format_height = img.shape[0] format_weight = img.shape[1] format_matrix = np.zeros((format_height, format_weight), dtype='uint8') for i in range(format_height): for j in range(format_weight): if img[i][j] == max_alive: # if value of matrix == 3, set it to 2 format_matrix[i][j] = 2 elif img[i][j] == num_alive: # if value of matrix == 2, set it to 1 format_matrix[i][j] = 1 return format_matrix # format the life matrix def format_life(img): format_height = img.shape[0] format_weight = img.shape[1] format_matrix = np.zeros((format_height, format_weight), dtype='uint8') for i in range(format_height): for j in range(format_weight): if img[i][j] > 1: format_matrix[i][j] = 1 return format_matrix def life_iterate(img): format_c = format_conv(convolve(img)) life_matric = format_life(img + format_c) return life_matric fig = plt.figure() plt.axis('off') print(img) im = plt.imshow(img) def animate(i): global img img = life_iterate(img) im.set_array(img) print(img) return [im] anim = animation.FuncAnimation(fig, animate, frames=200, interval=2000, blit=True) plt.show()
怎么处理边缘:
当做0处理
处理流程:
1. 卷积
2. 格式化
3. 迭代
方法二:调用opencv的卷积方法
def life_iterate(img): #format_c = format_conv(convolve(img)) format_c = format_conv(cv2_convolve(img)) life_matric = format_life(img + format_c) return life_matric def img_minusborder(border): return border[1: border.shape[0] - 1, 1: border.shape[1] - 1] def cv2_convolve(img): fil = np.array([[1, 1, 1], [1, 0, 1], [1, 1, 1]]) return img_minusborder(cv2.filter2D(img_addborder(img), -1, fil)) # function 2 to calaulate convolution def img_addborder(img): border_height = img.shape[0] + 2 border_weight = img.shape[1] + 2 border_matrix = np.zeros((border_height, border_weight), dtype='uint8') border_matrix[1: border_height - 1, 1: border_weight - 1] = img return border_matrix