我想将一个数组复制到另一个不同大小的数组。 我想要一个像这样的函数:
blit(destimg,src,dstlocation)
例如blit(zeros((7,7)),ones((3,3)),(4,4))
会导致
array([[ 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 1., 1., 1.],
[ 0., 0., 0., 0., 1., 1., 1.],
[ 0., 0., 0., 0., 1., 1., 1.]])
数组src
的左上角现在位于数组(4,4)
的{{1}}位置。
如果我destimg
我会得到:
blit(zeros((7,7)),ones((3,3)),(5,5))
数组array([[ 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 1., 1.],
[ 0., 0., 0., 0., 0., 1., 1.]])
不适合src
,但其左上角仍处于正确的位置。
答案 0 :(得分:3)
您可以计算适当的切片:
import numpy as np
def blit(dest, src, loc):
pos = [i if i >= 0 else None for i in loc]
neg = [-i if i < 0 else None for i in loc]
target = dest[[slice(i,None) for i in pos]]
src = src[[slice(i, j) for i,j in zip(neg, target.shape)]]
target[[slice(None, i) for i in src.shape]] = src
return dest
print(blit(np.zeros((7,7)), np.ones((3,3)), (5, 5)))
产量
[[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 1. 1.]
[ 0. 0. 0. 0. 0. 1. 1.]]
和
print(blit(np.zeros((7,7)), np.ones((3,3)), (-1, -1)))
产量
[[ 1. 1. 0. 0. 0. 0. 0.]
[ 1. 1. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]]
答案 1 :(得分:0)
我能够找到一个解决方案(有点冗长),必须有一个更优雅的方式,但在中期这样做。
from numpy import *
def blit(dest, src, loc):
th,tw=dest.shape
sh,sw=src.shape
sr = 0 if -loc[0]<0 else -loc[0]
fr = sh if loc[0]+sh<=th else sh-(loc[0]+sh-th)
sc = 0 if -loc[1]<0 else -loc[1]
fc = sw if loc[1]+sw<=tw else sw-(loc[1]+sw-th)
loc[0] = max(0,loc[0])
loc[1] = max(0,loc[1])
dest[loc[0]:loc[0]+sh-sr,loc[1]:loc[1]+sw-sc] = src[sr:fr,sc:fc]
dest = zeros((7,7))
src = ones((3,3))
loc = [5,5]
blit(dest, src, loc)
print dest
的产率:
[[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 1. 1.]
[ 0. 0. 0. 0. 0. 1. 1.]]
和
dest = zeros((7,7))
src = ones((3,3))
loc = [-1,-1]
blit(dest, src, loc)
print dest
产量
[[ 1. 1. 0. 0. 0. 0. 0.]
[ 1. 1. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0.]]
答案 2 :(得分:0)
这是我的实现方式:
def blit(a, b, offsets=(0,), as_shapes=False):
"""
Computes the slices of the overlapping regions of arrays <a> and <b>. If offsets are specified,
<b> will be shifted by these offsets before computing the overlap.
Example:
50
┌──────┐
│ │
65│ ┌───┼────┐
│ │ │ │50
└──┼───┘ │
└────────┘
55
<a> is the 65x50 array and <b> is the 50x55 array. The offsets are (32, 18). The returned
slices are [32:65, 18:50] for <a> and [0:33, 0:32] for <b>.
Arrays of different dimensions can be used (e.g. 3-dimensional RGB image and 2-dimensional
grayscale image) but the slices will only go up to min(a.ndim, b.ndim). An offset with more
elements than that will throw a ValueException.
Instead of arrays, shapes can be directly passed to the function by setting as_shapes to True.
:param a: an array object or a tuple is as_shape is True
:param b: an array object or a tuple is as_shape is True
:param offsets: a sequence of offsets
:param as_shapes: if True, <a> and <b> are expected to be array shapes rather than array
:return: a multidimensional slice for <a> followed by a multidimensional slice for <b>
"""
# Retrieve and check the array shapes and offset
if not as_shapes:
a, b = np.array(a, copy=False), np.array(b, copy=False)
a_shape, b_shape = a.shape, b.shape
else:
a_shape, b_shape = a, b
n = min(len(a_shape), len(b_shape))
if n == 0:
raise ValueError("Cannot overlap with an empty array")
offsets = tuple(offsets) + (0,) * (n - len(offsets))
if len(offsets) > n:
raise ValueError("Offset has more elements than either number of dimensions of the arrays")
# Compute the slices
a_slices, b_slices = [], []
for i, (a_size, b_size, offset) in enumerate(zip(a_shape, b_shape, offsets)):
a_min = max(0, offset)
a_max = min(a_size, max(b_size + offset, 0))
b_min = max(0, -offset)
b_max = min(b_size, max(a_size - offset, 0))
a_slices.append(slice(a_min, a_max))
b_slices.append(slice(b_min, b_max))
return tuple(a_slices), tuple(b_slices)
def paste(a, b, offsets=(0,), copy=True):
"""
Pastes array <b> into array <a> at position <offsets>
:param a: an array object
:param b: an array object
:param offsets: the position in <a> at which <b> is to be pasted
:param copy: whether to paste <b> in <a> or in a copy of <a>
:return: either <a> or a copy of <a> with <b> pasted on it
"""
out = np.array(a, copy=copy)
a_slice, b_slice = blit(a, b, offsets)
out[a_slice] = b[b_slice]
return out