numpy blit(将数组的一部分复制到另一个大小不同的数组)

2024-10-02 06:30:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我想把一个数组复制到另一个大小不同的数组。 我想要这样的函数:

blit(destimg,src,dstlocation)

例如blit(zeros((7,7)),ones((3,3)),(4,4))

会导致

^{pr2}$

数组src的左上中心现在位于数组destimg的位置(4,4)。在

如果我做了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不适合destimg,但它的左上角仍然位于右侧位置。在


Tags: 函数srconeszeros数组中心array我会
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)))

收益率

^{pr2}$

以及

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.]]

我能够找到一个解决方案(有点冗长),一定有一个更优雅的方式,但在中间时间这将做。在

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

产量:

^{pr2}$

以及

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.]]

以下是我的实现:

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

相关问题 更多 >

    热门问题