零填充切片在numpy中的数组末尾

Mic*_*ang 9 python numpy

在Numpy中,如果我正在切换数组的末尾,是否有一种零填充条目的方法,这样我得到的东西就是所需切片的大小?

例如,

>>> x = np.ones((3,3,))
>>> x
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])
>>> x[1:4, 1:4] # would behave as x[1:3, 1:3] by default
array([[ 1.,  1.,  0.],
       [ 1.,  1.,  0.],
       [ 0.,  0.,  0.]])
>>> x[-1:2, -1:2]
 array([[ 0.,  0.,  0.],
       [ 0.,  1.,  1.],
       [ 0.,  1.,  1.]])
Run Code Online (Sandbox Code Playgroud)

在视觉上,我希望越界区域为零填充:

在此输入图像描述

我正在处理图像,并希望零填充表示为我的应用程序移动图像.

我目前的计划是在切片之前使用np.pad使整个数组更大,但索引似乎有点棘手.有可能更容易的方法吗?

MSe*_*ert 6

据我所知,对于这样的问题,没有 numpy 解决方案(也不在我知道的任何包中)。你可以自己做,但即使你只想要基本的切片,这也将是一个非常非常复杂的过程。我建议你手动np.pad你的数组,并在你实际切片之前简单地偏移你的开始/停止/步骤。

但是,如果您需要支持的只是整数和切片而无需步骤,我有一些“工作代码”:

import numpy as np

class FunArray(np.ndarray):
    def __getitem__(self, item):

        all_in_slices = []
        pad = []
        for dim in range(self.ndim):
            # If the slice has no length then it's a single argument.
            # If it's just an integer then we just return, this is
            # needed for the representation to work properly
            # If it's not then create a list containing None-slices
            # for dim>=1 and continue down the loop
            try:
                len(item)
            except TypeError:
                if isinstance(item, int):
                    return super().__getitem__(item)
                newitem = [slice(None)]*self.ndim
                newitem[0] = item
                item = newitem
            # We're out of items, just append noop slices
            if dim >= len(item):
                all_in_slices.append(slice(0, self.shape[dim]))
                pad.append((0, 0))
            # We're dealing with an integer (no padding even if it's
            # out of bounds)
            if isinstance(item[dim], int):
                all_in_slices.append(slice(item[dim], item[dim]+1))
                pad.append((0, 0))
            # Dealing with a slice, here it get's complicated, we need
            # to correctly deal with None start/stop as well as with
            # out-of-bound values and correct padding
            elif isinstance(item[dim], slice):
                # Placeholders for values
                start, stop = 0, self.shape[dim]
                this_pad = [0, 0]
                if item[dim].start is None:
                    start = 0
                else:
                    if item[dim].start < 0:
                        this_pad[0] = -item[dim].start
                        start = 0
                    else:
                        start = item[dim].start
                if item[dim].stop is None:
                    stop = self.shape[dim]
                else:
                    if item[dim].stop > self.shape[dim]:
                        this_pad[1] = item[dim].stop - self.shape[dim]
                        stop = self.shape[dim]
                    else:
                        stop = item[dim].stop
                all_in_slices.append(slice(start, stop))
                pad.append(tuple(this_pad))

        # Let numpy deal with slicing
        ret = super().__getitem__(tuple(all_in_slices))
        # and padding
        ret = np.pad(ret, tuple(pad), mode='constant', constant_values=0)

        return ret
Run Code Online (Sandbox Code Playgroud)

这可以按如下方式使用:

>>> x = np.arange(9).reshape(3, 3)
>>> x = x.view(FunArray)
>>> x[0:2]
array([[0, 1, 2],
       [3, 4, 5]])
>>> x[-3:2]
array([[0, 0, 0],
       [0, 0, 0],
       [0, 0, 0],
       [0, 1, 2],
       [3, 4, 5]])
>>> x[-3:2, 2]
array([[0],
       [0],
       [0],
       [2],
       [5]])
>>> x[-1:4, -1:4]
array([[0, 0, 0, 0, 0],
       [0, 0, 1, 2, 0],
       [0, 3, 4, 5, 0],
       [0, 6, 7, 8, 0],
       [0, 0, 0, 0, 0]])
Run Code Online (Sandbox Code Playgroud)

请注意,这可能包含错误和“未干净编码”的部分,除了在琐碎的情况下,我从未使用过它。