numpy.pad() 函数有没有反向操作?

18 投票
5 回答
22300 浏览
提问于 2025-04-18 13:42

有没有一个函数可以做和 numpy.pad() 相反的事情呢?

我想找一个函数,可以在每个方向上均匀地减少一个 numpy 数组(矩阵)的维度。我试着用负值来调用 numpy.pad(),结果出现了错误:

import numpy as np

A_flat = np.array([0,1,2,3,4,5,6,7,8,9,10,11])
A = np.reshape(A_flat, (3,2,-1))

#this WORKS:
B = np.pad(A, ((1,1),(1,1),(1,1)), mode='constant')

# this DOES NOT WORK:
C = np.pad(B, ((-1,1),(1,1),(1,1)), mode='constant')

错误信息:ValueError: ((-1, 1), (1, 1), (1, 1)) 不能包含负值。

我明白这个 numpy.pad() 函数不接受负值,但有没有类似 numpy.unpad() 的函数呢?

5 个回答

1
def reverse_pad(arr: np.ndarray, padding: tuple):
"""Reverses padding for some numpy array

Args:
    arr (np.ndarray): Input numpy array
    padding (tuple): Padding used to padd array

Returns:
    np.ndarray: Numpy array with reversed padding
"""

reversed_padding = [
    slice(start_pad, dim - end_pad)  # dim tracks dimension length
    for ((start_pad, end_pad), dim) in zip(padding, arr.shape)
]

return arr[reversed_padding]

如果你给一个数组加了一些填充,比如这样:

arr = np.pad(arr, some_padding, mode="constant")

那么你可以用下面的方式把这个操作反过来:

arr = reverse_pad(arr, some_padding)

请告诉我这样是否有效!

2

这里有一个用于居中去除填充的函数:

def unpad(dens, pad):
    """
    Input:  dens   -- np.ndarray(shape=(nx,ny,nz))
            pad    -- np.array(px,py,pz)

    Output: pdens -- np.ndarray(shape=(nx-px,ny-py,nz-pz))
    """

    nx, ny, nz = dens.shape
    pl = pad // 2
    pr = pad - pl

    pdens = dens[pl[0]:nx-pr[0],
            pl[1]:ny-pr[1],
            pl[2]:nz-pr[2]]

    return pdens
5

一个通用的解决方案是这样的:

def unpad(x, pad_width):
    slices = []
    for c in pad_width:
        e = None if c[1] == 0 else -c[1]
        slices.append(slice(c[0], e))
    return x[tuple(slices)]

# Test
import numpy as np
pad_width = ((0, 0), (1, 0), (3, 4))

a = np.random.rand(10, 10, 10)
b = np.pad(a, pad_width, mode='constant')
c = unpad(b, pad_width)
np.testing.assert_allclose(a, c)
16

正如mdurant所建议的,直接使用切片索引就可以了:

In [59]: B[1:-1, 1:-1, 1:-1]
Out[59]: 
array([[[ 0,  1],
        [ 2,  3]],

       [[ 4,  5],
        [ 6,  7]],

       [[ 8,  9],
        [10, 11]]])
9

你想要的操作是:

C = np.pad(B, ((-1,1),(1,1),(1,1)), mode='constant')

可以用 pad 和一般的切片组合来替代:

C = np.pad(B, ((0,1),(1,1),(1,1)), mode='constant')[1:,...]

撰写回答