下面的代码检查 python 中对象像素的周围像素。
self.surr = [None, None, None, None, None, None, None, None]
for i in range(9):
#for x in range(-1, 2):
#for y in range(-1, 2):
if i != 5:
x = i % 3 - 2
y = int((i % 3) / 3) - 1
if x == 0 and y == 0:
pass
else:
PAI = allPixels[(self.x + x) % width][(self.y + y) % height] if allPixels[(self.x + x) % width][(self.y + y) % height] != None else None
self.surr[(y * 3) + x] = (PAI)
return self.surr
这将返回一个长度为 8 的列表,其中包含 Pixel
对象或 None
。 allPixels 是一个 2D 数组,还包含 Pixel
对象或 None
。
我尝试过注释掉的嵌套循环,但它们的运行速度比我当前使用的方法慢一点。然而,这仍然太慢,就像屏幕上有 3000 个像素一样,这是最终屏幕上总像素的下限,计算一下,每帧都会有很多东西。
如何使用 NumPy 或其他方法使其运行得更快?
如果您想查看完整代码,可以在这里找到:https://pastebin.com/EuutUVjS
感谢您给我的任何帮助!
最佳答案
您正在做的事情本质上需要循环 - 但如果您可以将该循环移动到 numpy 中,它通常会快 5-20 倍。
就您而言,您要做的是将每个像素与其邻居进行比较。如何将其作为数组范围的操作来做到这一点?简单:将数组与移位 1 的同一个数组进行比较。
这是一个更简单的示例:
>>> a = np.array([1,2,4,8,16])
>>> for i in range(1, len(a)):
... print(a[i] - a[i-1], end=' ')
1 2 4 8
>>> print(a[1:] - a[:-1])
[1 2 4 8]
因此,对于二维数组,它只是:
north = a[:-1]
ne = a[:-1,1:]
east = a[:,1:]
se = a[1:,1:]
south = a[1:]
sw = a[1:,:-1]
west = a[:,:-1]
nw = a[:-1,:-1]
请注意,这并没有浪费大量时间或内存来构建 8 个额外的数组;它只是在同一内存上创建 8 个 View 。
参见this answer on compsci有关使用这些移位数组进行康威生命游戏模拟的示例。
如果您想以不同的方式处理边界,您可能需要对数组进行“零扩展”,但这是您可能遇到的唯一复杂情况。
但是,如果您在 numpy 中存储 Python 对象,那么您能从 numpy 中获得的好处是有限的。通常,您想要存储数字数组。
我不知道你的 Pixel
里有什么对象,但让我们假设它们只是颜色值,如三个 float 。在这种情况下,您可以使用具有三个 float 的结构化数据类型的 2D 数组,或者仅使用 3D 数组(按 r-g-b 逐列),无论哪种方式都使用 NaN 值代替 None
.
如果这样做,阵列范围的操作可以以接近机器 native 的速度运行,包括使用 SIMD 操作实现数据并行。如果不这样做,则只会以 native 速度进行循环;循环内的算术仍然与非 Numpy Python 一样慢。
关于python - 有没有办法用Python中更有效的东西替换for循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50438206/