我是一名正在学习Python的视觉艺术家,以创建一套指定的艺术作品。在一个方面,我使用2160x3840网格编写Conway经典的生命游戏。
然而,该程序运行速度比我希望的要慢:它已经在我三岁的iMac上运行了24小时,我只处理了两个半“帧”。运行需要数周时间,我还有几次运行。
我运行了SnakeViz并且我的程序时间的93%用于单个功能,其中主要活动是一系列比较。根据康威的规则,所有“雀色”颜色和flashOfLifeColor都被视为“实时”单元格。
def isLive (theColor):
isCellLive = False
finchColor_1 = numpy.array([247, 238, 214])
finchColor_2 = numpy.array([202, 184, 88])
finchColor_3 = numpy.array([103, 81, 68])
flashOfLifeColor = numpy.array([249, 192, 0])
if (numpy.array_equal(theColor, finchColor_1)) or
(numpy.array_equal(theColor, finchColor_2)) or
(numpy.array_equal(theColor, finchColor_3)) or
(numpy.array_equal(theColor, flashOfLifeColor)):
isCellLive = True
return isCellLive
是否有更好(更快)的方式来编写if语句?除了优化之外我还能做些什么来加快速度吗?
谢谢,
- 达林
编辑:
这是调用isLive的函数,以帮助理解我在做什么。我还想再次提到我在Python编程方面很陌生,并且根本不了解对象编程,而不是任何高级技术 - 很难解读我所看到的Conway规则的一些实现。网络。
def countNeighborsNine(theArray, row, column):
numberOfNeighbors = 0
maxRow, maxColumn, depth = theArray.shape
for rowModifier in range (-1,2):
for columnModifier in range (-1, 2):
rowNeighborPointer = (row + rowModifier) % maxRow
columnNeighborPointer = (column + columnModifier) % maxColumn
thePixel = theArray[rowNeighborPointer, columnNeighborPointer]
if isLive(thePixel):
numberOfNeighbors = numberOfNeighbors + 1
return numberOfNeighbors
答案 0 :(得分:2)
这是一个可能的解决方案。 R,G和B各自的图像颜色可能在0..255
范围内。我会先将其转换为整个图像的唯一“颜色ID”(易于处理)。
cid = grid_r * 256 * 256 + grid_g * 256 + grid_b
对你的生死名单做同样的事情:
def get_id(a):
return a[0] * 256 * 256 + a[1] * 256 + a[2]
live_colours = np.array([get_id(finchColor_1), get_id(finchColor_2), get_id(finchColor_3), get_id(flashOfLifeColor)])
现在,您可以在一个命令中获取所有“实时”单元格:
alive = np.in1d(cid, live_colours).reshape(cid.shape)
此处,alive
将是True
和False
元素的2160x3840数组。 np.in1d
获取cid
中的每个元素,如果它位于True
,则返回live_colours
。返回的数组是1-d,因此您需要将其重新整形为与原始图像相同的形状。
编辑 - 现在使用它来计算每个单元格的活动邻居数量。首先,我定义了一个二维滚动功能。
def shifter(x, a, b):
return np.roll(np.roll(x, a, axis=0), b, axis=1)
我取alive
数组,并在所有4个方面用“死”单元填充它:
width = 2160
height = 3840
biglive = np.zeros((width + 2, height + 2))
biglive[1:-1, 1:-1] = alive.astype(int)
live_count = shifter(biglive, -1, -1) + shifter(biglive, -1, 0) + shifter(biglive, -1, 1) + shifter(biglive, 0, -1) + shifter(biglive, 0, 1) + shifter(biglive, 1, -1) + shifter(biglive, 1, 0) + shifter(biglive, 1, 1)
我们忽略了最后填充的零个单元格。
live_count = live_count[1:-1, 1:-1]
这是一个2160x3840网格,其中每个单元格包含活动邻居的数量。我生成了一个随机图像,整个过程需要几秒钟来计算完整的2160x3840集的活动邻居数。
答案 1 :(得分:1)
只是有人建议你自己找到最好的方法。
从一个纯粹的python项目开始,然后是一个numpy项目。
分离游戏逻辑和可视化。
例如,一个数组用于区分alive / dead,另一个用于计算邻居。 使用imshow(neighbors,cmap = my_conway_map)进行可视化。
永远不要在numpy数组上使用for循环,它很慢。
最小例子:
world=randint(0,2,(5,5))
mask=ones((3,3))
mask[1,1]=0
neighb=scipy.signal.convolve2d(world,mask,'same')
subplot(121)
a=imshow(world,interpolation='none',cmap=cm.Greys)
subplot(122)
colorbar()
b=imshow(neighb,interpolation='none')
show()