python - 地图地形分析:numpy.roll 函数的替代方案?
问题描述
我正在尝试分析StarCraft 2 bot API给出的地图地形。
此分析的初学者任务是为收割者寻找悬崖,这是 SC2 中可以上下悬崖的特殊单位。
为了解决这个问题,我分析了点本身不可路径(=悬崖)并且北部和南部两个点是可路径的点。在数组中,可路径点标记为 1,不可路径点为 0。
地形图以 2D numpy 数组的形式存在。以下是较大的 200x200 阵列的一小段摘录:
import numpy as np
example = np.array([[0, 0, 0, 0],
[0, 1, 1, 0],
[0, 0, 0, 0],
[0, 1, 1, 0],
[0, 0, 0, 0]])
在这里,点 [2, 1] 和 [2, 2] 将匹配点本身不可路径 (=0) 且它们上方和下方的点可路径 (=1) 的标准。
这可以通过以下代码实现:
above = np.roll(example, 1, axis=0) # Shift rows downwards
below = np.roll(example, -1, axis=0) # Shift rows upwards
result = np.zeros_like(example) # Create array with zeros
result[(example == 0) & (above == 1) & (below == 1)] = 1 # Set cells to 1 that match condition
print(repr(result))
# array([[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 1, 1, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]])
现在我的问题是,是否可以用更少的代码来实现相同的目标?
np.roll 函数每次都会创建一个新的 np.array 对象,因此分析数百个附近的点可能会导致 100 行不必要的代码和高内存使用。
我试图找到类似的东西
result = np.zeros_like(example)
result[(example == 0) & (example[-1, 0] == 1) & (example[1, 0 == 1)] = 1
# or
result[(example == 0) & ((example[-1:2, 0].sum() == 2)] = 1
这里括号中的数字显示了与当前分析点的相对位置,但我不知道是否有办法让它与 numpy.
此外,在检查“上方”点时,第零行的结果也不清楚:它可以访问最后一行,导致错误或返回默认值(0 或 1)。
编辑: 我找到了这篇文章,它指向了可以在这里应用的scipy convolve2d函数,这可能是我正在寻找的:
import numpy as np
from scipy import signal
example = np.array([[0, 0, 0, 0],
[0, 1, 1, 0],
[0, 0, 0, 0],
[0, 1, 1, 0],
[0, 0, 0, 0]])
kernel = np.zeros((3, 3), dtype=int)
kernel[::2, 1] = 1
print(repr(kernel))
# array([[0, 1, 0],
# [0, 0, 0],
# [0, 1, 0]])
result2 = signal.convolve2d(example, kernel, mode="same")
print(repr(result2))
# array([[0, 1, 1, 0],
# [0, 0, 0, 0],
# [0, 2, 2, 0],
# [0, 0, 0, 0],
# [0, 1, 1, 0]])
result2[result2 < 2] = 0
result2[result2 == 2] = 1
print(repr(result2))
# array([[0, 0, 0, 0],
# [0, 0, 0, 0],
# [0, 1, 1, 0],
# [0, 0, 0, 0],
# [0, 0, 0, 0]])
Edit2: 另一种解决方案可能是scipy.ndimage.minimum_filter似乎工作类似:
import numpy as np
from scipy import ndimage
example = np.array([[0, 0, 0, 0],
[0, 1, 1, 0],
[0, 0, 0, 0],
[0, 1, 1, 0],
[0, 0, 0, 0]])
kernel = np.zeros((3, 3), dtype=int)
kernel[::2, 1] = 1
print(repr(kernel))
# array([[0, 1, 0],
# [0, 0, 0],
# [0, 1, 0]])
result3 = ndimage.minimum_filter(example, footprint=kernel_vertical, mode="constant")
print(repr(result3))
# array([[0, 0, 0, 0],
# [0, 0, 0, 0],
# [0, 1, 1, 0],
# [0, 0, 0, 0],
# [0, 0, 0, 0]])
解决方案
推荐阅读
- php - 将美分转换为美元并返回浮点值
- python-3.x - 打印总和大于或等于目标的最小子数组
- python - 如何解释热图(或一般)上的负相关?
- javascript - 如何在使用 sweetalert2 显示下一个警报之前等待操作完成
- ios - UITabBar 文本未与横向模式下的图标正确对齐
- flutter - 用户如何在颤抖中互相发送付款
- python - Sqlalchemy 搜索带有数组且没有键的 JSONB 列
- javascript - 如何删除数组对象中数组内的项目?javascript
- mysql - 当主键到达顶部时,如何告诉 MySQL 重置主键增量?
- javascript - 使用 TypeScript 创建实体对象的最佳方法?