2013-04-07 257 views
8

我在2D地图由ndarray表示的项目中使用numpy的和Python:如何将Numpy数组切片到边界?

map = [[1,2,3,4,5], 
     [2,3,4,2,3], 
     [2,2,2,1,2], 
     [3,2,1,2,3], 
     [4,6,5,7,4]] 
MAP_WIDTH = 5, MAP_HEIGHT = 5 

的对象具有一个元组的位置:

actor.location = (3,3) 

和一个视野范围:

actor.range = 2 

如何编写函数actor.view_map(map),使地图返回演员位置周围的区域直至范围。例如(使用上述地图),

range = 1 
location = (3, 2) 
=> 
[[2,3,4], 
[3,4,2], 
[2,2,1]] 

,但如果演员的范围扩展得太远我想要的地图充满了-1:

range = 1 
location = (1,1) 
[[-1,-1,-1], 
[-1, 1, 2], 
[-1, 2, 3]] 

最简单的情况下是一系列的0,返回当前平方:

range = 0 
location = (1, 2) 
[[2]] 

如何将我的地图切片到某个边界?

+1

'actor.range'会有多少变化?如果它总是小于某个值(相对较小),那么就有一个简单的优化(用-1缓冲边并写一个简单的包装类)。 – 2013-04-07 20:54:28

+0

它将始终小于地图宽度/高度的一半 - 但如果我在该级别向地图添加边界,则会将其大小加倍(?)... – sdasdadas 2013-04-07 20:56:08

+1

更接近四倍(面积==长度平方),实际上。尽管如此,如果你能够承担内存使用量,它会大大加快索引速度。 – 2013-04-07 20:58:25

回答

4

因此,感谢Joe Kington,我在地图周围添加了一个边框(填充-1s)。

这里是我做到了,但因为我刚开始用的语言/库这可能不是非常符合Python:

map = numpy.random.randint(10, size=(2 * World.MAP_WIDTH, 2 * World.MAP_HEIGHT)) 
map[0 : World.MAP_WIDTH/4, :] = -1 
map[7 * World.MAP_WIDTH/4 : 2 * World.MAP_WIDTH, :] = -1 
map[:, 0 : World.MAP_HEIGHT/4] = -1 
map[:, 7 * World.MAP_HEIGHT/4 : 2 * World.MAP_WIDTH] = -1 
+3

您可以使用函数'np.pad'在地图上添加边框:'np.pad(map,1,mode ='constant',constant_values = -1)' – askewchan 2013-04-08 03:18:46

+0

提示:避免使用'map'作为变量名称。这是python中的一个内置函数。 https://docs.python.org/3/library/functions.html#map – grisaitis 2016-03-03 17:19:42

2

这里有一个小类Box,使使用更方便盒 -

from __future__ import division 
import numpy as np 

class Box: 
    """ B = Box(2d numpy array A, radius=2) 
     B.box(j, k) is a box A[ jk - 2 : jk + 2 ] clipped to the edges of A 
     @askewchan, use np.pad (new in numpy 1.7): 
      padA = np.pad(A, pad_width, mode="constant", edge=-1) 
      B = Box(padA, radius) 
    """ 

    def __init__(self, A, radius): 
     self.A = np.asanyarray(A) 
     self.radius = radius 

    def box(self, j, k): 
     """ b.box(j, k): square around j, k clipped to the edges of A """ 
     return self.A[ self.box_slice(j, k)] 

    def box_slice(self, j, k): 
     """ square, jk-r : jk+r clipped to A.shape """ 
      # or np.clip ? 
     r = self.radius 
     return np.s_[ max(j - r, 0) : min(j + r + 1, self.A.shape[0]), 
         max(k - r, 0) : min(k + r + 1, self.A.shape[1])] 

#............................................................................... 
if __name__ == "__main__": 
    A = np.arange(5*7).reshape((5,7)) 
    print "A:\n", A 
    B = Box(A, radius=2) 
    print "B.box(0, 0):\n", B.box(0, 0) 
    print "B.box(0, 1):\n", B.box(0, 1) 
    print "B.box(1, 2):\n", B.box(1, 2) 
+0

我还没有机会尝试它,但谢谢你的答复! – sdasdadas 2013-04-08 21:30:51

+0

我喜欢这个,从我这里得到赞扬:) – 2014-10-31 16:00:23