添加不同尺寸/形状的NumPy矩阵

fra*_*xel 9 python numpy

简而言之:我有两个矩阵(或数组):

import numpy

block_1 = numpy.matrix([[ 0, 0, 0, 0, 0],
                        [ 0, 0, 0, 0, 0],
                        [ 0, 0, 0, 0, 0],
                        [ 0, 0, 0, 0, 0]])

block_2 = numpy.matrix([[ 1, 1, 1],
                        [ 1, 1, 1],
                        [ 1, 1, 1],
                        [ 1, 1, 1]])
Run Code Online (Sandbox Code Playgroud)

block_2block_1元素坐标系中有位移.

pos = (1,1)
Run Code Online (Sandbox Code Playgroud)

我希望能够(快速)添加它们,以获得:

[[0 0 0 0 0]
 [0 1 1 1 0]
 [0 1 1 1 0]
 [0 1 1 1 0]]
Run Code Online (Sandbox Code Playgroud)

总之:我想快速地将两个不同的形状矩阵添加到一起,其中一个矩阵可以移位.得到的矩阵必须具有第一矩阵的形状,并且两个矩阵之间的重叠元素相加.如果没有重叠,则只返回未突变的第一个矩阵.

我有一个工作正常的功能,但它有点难看,并且元素:

def add_blocks(block_1, block_2, pos):
    for i in xrange(0, block_2.shape[0]):
        for j in xrange(0, block_2.shape[1]):
            if (i + pos[1] >= 0) and (i + pos[1] < block_1.shape[0])
               and (j + pos[0] >= 0) and (j + pos[0] < block_1.shape[1]):
                block_1[pos[1] + i, pos[0] + j] += block_2[i,j]
    return block_1
Run Code Online (Sandbox Code Playgroud)

广播或切片可能会这样吗?

我觉得也许我错过了一些明显的东西.

Ewy*_*ato 16

一个看起来像MATLAB解决方案的简单解决方案是:

import numpy as np

block1 = np.zeros((5,4))
block2 = np.ones((3,2))

block1[1:4,2:4] += block2  # use array slicing

print(block1)

[[0. 0. 0. 0.]
 [0. 0. 1. 1.]
 [0. 0. 1. 1.]
 [0. 0. 1. 1.]
 [0. 0. 0. 0.]]
Run Code Online (Sandbox Code Playgroud)

因此将其打包为可重用的功能:

import numpy as np

def addAtPos(mat1, mat2, xypos):
    """
    Add two matrices of different sizes in place, offset by xy coordinates
    Usage:
      - mat1: base matrix
      - mat2: add this matrix to mat1
      - xypos: tuple (x,y) containing coordinates
    """
    x, y = xypos
    ysize, xsize = mat2.shape
    xmax, ymax = (x + xsize), (y + ysize)
    mat1[y:ymax, x:xmax] += mat2
    return mat1

block1 = np.zeros((5,4))
block2 = np.ones((3,2))
pos = (2,1)
print(addAtPos(block1, block2, pos))

[[0. 0. 0. 0.]
 [0. 0. 1. 1.]
 [0. 0. 1. 1.]
 [0. 0. 1. 1.]
 [0. 0. 0. 0.]]
Run Code Online (Sandbox Code Playgroud)


jor*_*eca 5

您只需要找到重叠范围,然后使用切片添加数组即可。

b1 = np.zeros((4,5))
b2 = np.ones((4,3))
pos_v, pos_h = 2, 3  # offset
v_range1 = slice(max(0, pos_v), max(min(pos_v + b2.shape[0], b1.shape[0]), 0))
h_range1 = slice(max(0, pos_h), max(min(pos_h + b2.shape[1], b1.shape[1]), 0))

v_range2 = slice(max(0, -pos_v), min(-pos_v + b1.shape[0], b2.shape[0]))
h_range2 = slice(max(0, -pos_h), min(-pos_h + b1.shape[1], b2.shape[1]))

b1[v_range1, h_range1] += b2[v_range2, h_range2]
Run Code Online (Sandbox Code Playgroud)

它们是就地添加的,但是您也可以创建一个新的数组。我可能已经错过了一些极端情况,但似乎工作正常。