分配给numpy数组的

时间:2016-10-24 21:42:43

标签: python numpy indexing

我有一张大图片A和一张较小的图片B,两者都表示为2-D numpy数组。我想使用A作为画布,并在其上面编写B的翻译副本,以六边形排列。我无法理解的部分是如何处理它,使图像垂直和水平包裹 - 基本上我想要的是将(填充的,必要的)子图像定期镶嵌到圆环上。 / p>

我已经看过numpy.takenumpy.roll的讨论了 wrapping around slices in Python / numpy这告诉我如何访问并返回数据的包装切片的 副本 ,但我想分配给它 - 即,任意整数rowOffsetcolumnOffset我想做的相当于:

  A = numpy.zeros((5,11), int)
  B = numpy.array([[1,2,3,4,5,6,7]]) * numpy.array([[10,100,1000]]).T
  # OK, we wouldn't be able to fit more than one or two copies of B into A, but they demonstrate the wrapped placement problem

  wrappedRowIndices = ( numpy.arange(B.shape[0]) + rowOffset ) % A.shape[0]
  wrappedColumnIndices = ( numpy.arange(B.shape[1]) + columnOffset ) % A.shape[1]
  A[ wrappedRowIndices,  : ][ :, wrappedColumnIndices ] = B 

我从评论on the question中看到, 并且从对numpy数组的表示方式的反思来看,包裹切片无法以此要求的方式返回view

是否有(Y)以这种方式分配给数组的包装切片的方法,或者(X)用于执行我试图实现的曲面细分的现有实用程序?

3 个答案:

答案 0 :(得分:3)

np.put相当于np.take

In [1270]: A=np.arange(10)
In [1271]: np.take(A,[8,9,10,11],mode='wrapped')
Out[1271]: array([8, 9, 0, 1])
In [1272]: np.put(A,[8,9,10,11],[10,11,12,13],mode='wrapped')
In [1273]: A
Out[1273]: array([12, 13,  2,  3,  4,  5,  6,  7, 10, 11])
In [1274]: np.take(A,[8,9,10,11],mode='wrapped')
Out[1274]: array([10, 11, 12, 13])

其文档建议np.placenp.putmask(以及np.copyto)。我还没有那么多地使用它们,但是可能会构建一个掩码,并重新安排B进行复制。

=================

这是place的实验:

In [1313]: A=np.arange(24).reshape(4,6)
In [1314]: mask=np.zeros(A.shape,bool)
In [1315]: mask[:3,:4]=True
In [1316]: B=-np.arange(12).reshape(3,4)

所以我mask的尺寸与A的尺寸相同,并且有一个'孔' B的大小。

我可以mask方式推送Bplace以及A wrapped中的值。

In [1317]: np.place(A, np.roll(mask,-2,0), np.roll(B,1,0).flat)
In [1318]: A
Out[1318]: 
array([[ -8,  -9, -10, -11,   4,   5],
       [  6,   7,   8,   9,  10,  11],
       [  0,  -1,  -2,  -3,  16,  17],
       [ -4,  -5,  -6,  -7,  22,  23]])

用2d卷

In [1332]: m=np.roll(np.roll(mask,-2,0),-1,1)
In [1333]: m
Out[1333]: 
array([[ True,  True,  True, False, False,  True],
       [False, False, False, False, False, False],
       [ True,  True,  True, False, False,  True],
       [ True,  True,  True, False, False,  True]], dtype=bool)
In [1334]: b=np.roll(np.roll(B,1,0),-1,1)
In [1335]: b
Out[1335]: 
array([[ -9, -10, -11,  -8],
       [ -1,  -2,  -3,   0],
       [ -5,  -6,  -7,  -4]])
In [1336]: A=np.zeros((4,6),int)
In [1337]: np.place(A, m, b.flat)
In [1338]: A
Out[1338]: 
array([[ -9, -10, -11,   0,   0,  -8],
       [  0,   0,   0,   0,   0,   0],
       [ -1,  -2,  -3,   0,   0,   0],
       [ -5,  -6,  -7,   0,   0,  -4]])

答案 1 :(得分:2)

您当前的代码分为__getitem____setitem__。正如您所指出的,__getitem__不会返回视图,因此__setitem__最终会修改副本。

你需要在一个__setitem__(即一组括号)中完成整个事情:

A[wrappedRowIndices[:,np.newaxis], wrappedColumnIndices] = B

由于广播,这相当于:

A[wrappedRowIndices[:,np.newaxis], wrappedColumnIndices[np.newaxis,:]] = B

使用多个数组进行索引时,规则是:

# ... here is NOT the python Ellipsis!
y = x[a, b, c, ...]
y[i, j, ..] = x[a[i,j,...], b[i,j,...], ...]

实际上有一个内置的,np.ix_()

A[np.ix_(wrappedRowIndices, wrappedColumnIndices)] = B

推广到ND,你得到:

def place_wrapped(canvas, brush, position):
    assert canvas.ndim == brush.ndim == len(position)
    ind = np.ix_(*(
        (np.arange(b_dim) + shift) % c_dim
        for b_dim, c_dim, shift in zip(brush.shape, canvas.shape, position)
    ))
    canvas[ind] = brush

答案 2 :(得分:1)

这是一个根据hpaulj的答案解决我的问题Y的功能。然而,这可能不是解决X的最有效方法,因为在numpy.roll中完成了所有繁重的工作。

import numpy

def place_wrapped(canvas, brush, position):
    mask = numpy.zeros(canvas.shape, bool)
    mask[[slice(extent) for extent in brush.shape]] = True
    for axis, shift in enumerate(position):
        canvas_extent = canvas.shape[axis]
        brush_extent = brush.shape[axis]
        shift %= canvas_extent
        if shift:
            mask = numpy.roll(mask, shift, axis=axis)
            nwrapped = shift + brush_extent - canvas_extent
            if nwrapped > 0: brush = numpy.roll(brush, nwrapped, axis=axis)
    numpy.place(canvas, mask, brush.flat)


A = numpy.zeros((5,11), int)
B = numpy.array([[1,2,3,4,5,6,7]]) * numpy.array([[10,100,1000]]).T
print(B)

rowOffset = 3
columnOffset = 7
place_wrapped(A, B, (rowOffset, columnOffset))
print(A)

Eric的纠正方法也有效,我认为它必须更有效率,因为它不需要复制任何数据:

def place_wrapped2(canvas, brush, position):
    ind = [
        ((numpy.arange(brush.shape[axis]) + shift) % canvas.shape[axis]).reshape([
            extent if i == axis else 1
            for i, extent in enumerate(brush.shape)
        ])
        for axis, shift in enumerate(position)
    ]
    canvas[ind] = brush

A *= 0 # reset
place_wrapped2(A, B, (rowOffset, columnOffset))
print(A)