我有一张大图片A
和一张较小的图片B
,两者都表示为2-D numpy
数组。我想使用A
作为画布,并在其上面编写B
的翻译副本,以六边形排列。我无法理解的部分是如何处理它,使图像垂直和水平包裹 - 基本上我想要的是将(填充的,必要的)子图像定期镶嵌到圆环上。 / p>
我已经看过numpy.take
和numpy.roll
的讨论了
wrapping around slices in Python / numpy这告诉我如何访问并返回数据的包装切片的 副本 ,但我想分配给它 - 即,任意整数rowOffset
和columnOffset
我想做的相当于:
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)用于执行我试图实现的曲面细分的现有实用程序?
答案 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.place
和np.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
方式推送B
和place
以及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)