我想知道如何使用带有numpy版本1.5.0的python 2.6.6用零填充2D numpy数组。抱歉!但这些是我的局限。因此我无法使用np.pad
。例如,我想用{0}填充a
,使其形状与b
匹配。我之所以这么做是因为我能做到:
b-a
这样
>>> a
array([[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.]])
>>> b
array([[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.]])
>>> c
array([[1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0]])
我能想到这样做的唯一方法是追加,但这看起来很难看。是否有一个更清洁的解决方案可能使用b.shape
?
编辑, 谢谢MSeiferts的回答。我不得不把它清理一下,这就是我得到的:
def pad(array, reference_shape, offsets):
"""
array: Array to be padded
reference_shape: tuple of size of ndarray to create
offsets: list of offsets (number of elements must be equal to the dimension of the array)
will throw a ValueError if offsets is too big and the reference_shape cannot handle the offsets
"""
# Create an array of zeros with the reference shape
result = np.zeros(reference_shape)
# Create a list of slices from offset to offset + shape in each dimension
insertHere = [slice(offsets[dim], offsets[dim] + array.shape[dim]) for dim in range(array.ndim)]
# Insert the array in the result at the specified offsets
result[insertHere] = array
return result
答案 0 :(得分:86)
非常简单,您可以使用参考形状创建一个包含零的数组:
result = np.zeros(b.shape)
# actually you can also use result = np.zeros_like(b)
# but that also copies the dtype not only the shape
然后将数组插入所需的位置:
result[:a.shape[0],:a.shape[1]] = a
并且你已经填补了它:
print(result)
array([[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0.]])
如果您定义应插入左上角元素的位置
,也可以使它更通用一些result = np.zeros_like(b)
x_offset = 1 # 0 would be what you wanted
y_offset = 1 # 0 in your case
result[x_offset:a.shape[0]+x_offset,y_offset:a.shape[1]+y_offset] = a
result
array([[ 0., 0., 0., 0., 0., 0.],
[ 0., 1., 1., 1., 1., 1.],
[ 0., 1., 1., 1., 1., 1.],
[ 0., 1., 1., 1., 1., 1.]])
但请注意,您的偏移量不会超过允许范围。例如,对于x_offset = 2
,这将失败。
如果您有任意数量的维度,则可以定义切片列表以插入原始数组。我发现有趣的是玩一下并创建一个填充函数,可以填充(带偏移)一个任意形状的数组,只要数组和引用具有相同的维数并且偏移量不是太大。
def pad(array, reference, offsets):
"""
array: Array to be padded
reference: Reference array with the desired shape
offsets: list of offsets (number of elements must be equal to the dimension of the array)
"""
# Create an array of zeros with the reference shape
result = np.zeros(reference.shape)
# Create a list of slices from offset to offset + shape in each dimension
insertHere = [slice(offset[dim], offset[dim] + array.shape[dim]) for dim in range(a.ndim)]
# Insert the array in the result at the specified offsets
result[insertHere] = a
return result
以及一些测试用例:
import numpy as np
# 1 Dimension
a = np.ones(2)
b = np.ones(5)
offset = [3]
pad(a, b, offset)
# 3 Dimensions
a = np.ones((3,3,3))
b = np.ones((5,4,3))
offset = [1,0,0]
pad(a, b, offset)
答案 1 :(得分:76)
NumPy 1.7.0(添加numpy.pad
时)已经很老了(它于2013年发布)所以即使问题是没有使用这个功能我想的了解如何使用numpy.pad
实现这一目标可能很有用。
实际上非常简单:
>>> import numpy as np
>>> a = np.array([[ 1., 1., 1., 1., 1.],
... [ 1., 1., 1., 1., 1.],
... [ 1., 1., 1., 1., 1.]])
>>> np.pad(a, [(0, 1), (0, 1)], mode='constant')
array([[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0.]])
在这种情况下,我使用0
是mode='constant'
的默认值。但它也可以通过显式传递来指定:
>>> np.pad(a, [(0, 1), (0, 1)], mode='constant', constant_values=0)
array([[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0.]])
以防第二个参数([(0, 1), (0, 1)]
)似乎令人困惑:每个列表项(在本例中为元组)对应于维度,其中的项目表示之前的填充(第一个元素)和之后(第二个元素)。所以:
[(0, 1), (0, 1)]
^^^^^^------ padding for second dimension
^^^^^^-------------- padding for first dimension
^------------------ no padding at the beginning of the first axis
^--------------- pad with one "value" at the end of the first axis.
在这种情况下,第一个和第二个轴的填充是相同的,所以也可以传入2元组:
>>> np.pad(a, (0, 1), mode='constant')
array([[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0.]])
如果之前和之后的填充相同,甚至可以省略元组(虽然在这种情况下不适用):
>>> np.pad(a, 1, mode='constant')
array([[ 0., 0., 0., 0., 0., 0., 0.],
[ 0., 1., 1., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0., 0.]])
或者如果之前和之后的填充相同但轴不同,您也可以省略内部元组中的第二个参数:
>>> np.pad(a, [(1, ), (2, )], mode='constant')
array([[ 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
但是我倾向于总是使用明确的一个,因为它只是容易犯错误(当NumPys的期望与你的意图不同时):
>>> np.pad(a, [1, 2], mode='constant')
array([[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.]])
这里NumPy认为你想要在所有轴之前填充1个元素,在每个轴之后填充2个元素!即使您打算在轴1中填充1个元素,也为轴2填充2个元素。
我使用了元组列表作为填充,请注意,这只是"我的约定",您还可以使用列表或元组列表,甚至是元组的元组。 NumPy只检查参数的长度(或者如果它没有长度)和每个项目的长度(或者如果它有长度)!
答案 2 :(得分:6)
我了解您的主要问题是您需要计算d=b-a
,但您的数组有不同的大小。不需要中间填充c
你可以在没有填充的情况下解决这个问题:
import numpy as np
a = np.array([[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.]])
b = np.array([[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.]])
d = b.copy()
d[:a.shape[0],:a.shape[1]] -= a
print d
输出:
[[ 2. 2. 2. 2. 2. 3.]
[ 2. 2. 2. 2. 2. 3.]
[ 2. 2. 2. 2. 2. 3.]
[ 3. 3. 3. 3. 3. 3.]]
答案 3 :(得分:0)
如果您需要向数组添加1s的栅栏:
>>> mat = np.zeros((4,4), np.int32)
>>> mat
array([[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]])
>>> mat[0,:] = mat[:,0] = mat[:,-1] = mat[-1,:] = 1
>>> mat
array([[1, 1, 1, 1],
[1, 0, 0, 1],
[1, 0, 0, 1],
[1, 1, 1, 1]])
答案 4 :(得分:0)
我知道我有点晚了,但是如果您想执行相对填充(aka边缘填充),可以通过以下方法实现它。请注意,分配的第一个实例会导致零填充,因此您可以将其用于零填充和相对填充(这是将原始数组的边值复制到填充数组中的地方)。
def replicate_padding(arr):
"""Perform replicate padding on a numpy array."""
new_pad_shape = tuple(np.array(arr.shape) + 2) # 2 indicates the width + height to change, a (512, 512) image --> (514, 514) padded image.
padded_array = np.zeros(new_pad_shape) #create an array of zeros with new dimensions
# perform replication
padded_array[1:-1,1:-1] = arr # result will be zero-pad
padded_array[0,1:-1] = arr[0] # perform edge pad for top row
padded_array[-1, 1:-1] = arr[-1] # edge pad for bottom row
padded_array.T[0, 1:-1] = arr.T[0] # edge pad for first column
padded_array.T[-1, 1:-1] = arr.T[-1] # edge pad for last column
#at this point, all values except for the 4 corners should have been replicated
padded_array[0][0] = arr[0][0] # top left corner
padded_array[-1][0] = arr[-1][0] # bottom left corner
padded_array[0][-1] = arr[0][-1] # top right corner
padded_array[-1][-1] = arr[-1][-1] # bottom right corner
return padded_array
对此的最佳解决方案是numpy的pad方法。
平均5次运行后,具有相对填充的np.pad仅比上面定义的功能好8%
。这表明这是相对填充和零填充的最佳方法。
#My method, replicate_padding
start = time.time()
padded = replicate_padding(input_image)
end = time.time()
delta0 = end - start
#np.pad with edge padding
start = time.time()
padded = np.pad(input_image, 1, mode='edge')
end = time.time()
delta = end - start
print(delta0) # np Output: 0.0008790493011474609
print(delta) # My Output: 0.0008130073547363281
print(100*((delta0-delta)/delta)) # Percent difference: 8.12316715542522%
答案 5 :(得分:0)
Tensorflow 还实现了用于调整/填充图像大小的函数 tf.image.pad tf.pad。
padded_image = tf.image.pad_to_bounding_box(image, top_padding, left_padding, target_height, target_width)
padded_image = tf.pad(image, paddings, "CONSTANT")
这些函数的工作方式与 tensorflow 的其他输入管道功能一样,对于机器学习应用程序来说效果会更好。