python 0으로 numpy 배열을 채우는 방법


99

numpy 버전 1.5.0과 함께 python 2.6.6을 사용하여 2D numpy 배열을 0으로 채우는 방법을 알고 싶습니다. 죄송합니다! 그러나 이것이 나의 한계입니다. 따라서 사용할 수 없습니다 np.pad. 예를 들어, a모양이 일치하도록 0으로 채우고 싶습니다 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

답변:


161

매우 간단하게 참조 모양을 사용하여 0을 포함하는 배열을 만듭니다.

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)

그냥 내가 필요한 경우를 요약 : 원점에 삽입, 임의의 크기의 경우 :padded = np.zeros(b.shape) padded[tuple(slice(0,n) for n in a.shape)] = a
shaneb

170

NumPy 1.7.0 ( numpy.pad추가 되었을 때 )은 지금 꽤 오래되었습니다 (2013 년에 출시되었습니다). 그래서 질문에서 그 기능 을 사용하지 않고 방법 요청했지만 .NET을 사용하여 어떻게 달성 할 수 있는지 아는 것이 유용 할 것이라고 생각했습니다 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는 인수의 길이 (또는 길이가없는 경우)와 각 항목의 길이 (또는 길이가있는 경우) 만 확인합니다!


5
정말 잘 설명되어 있습니다. 원본 문서보다 훨씬 낫습니다. 감사.
M.Innat

mode='constant'합리적인 기본값이므로 선택적 키워드 없이도 0으로 패딩을 수행 할 수 있으므로 코드를 약간 더 읽기 쉽게 만들 수 있습니다.
divenex

3D numpy 배열의 3 차원에만 패딩을 추가하려면 어떻게해야합니까?
Ramsha Siddiqui 20. 9.

@RamshaSiddiqui 패딩해서는 안되는 차원에 0을 사용할 수 있습니다.
MSeifert

9

나는 당신의 주요 문제가 당신이 계산해야한다는 것을 이해합니다. 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.]]

사실, 그의 특정한 경우에 그는 반드시 패딩 할 필요는 없지만 패딩과 접근 방식이 동일한 극소수의 산술 연산 중 하나입니다. 그럼에도 불구하고 좋은 대답!
MSeifert

1
뿐만 아니라. 이것은 또한 제로 패딩보다 메모리 효율성이 더 높을 수 있습니다.
norok2

0

배열에 울타리 1을 추가해야하는 경우 :

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

0

나는 이것에 약간 늦었다는 것을 알고 있지만 상대 패딩 (일명 가장자리 패딩)을 수행하려는 경우이를 구현할 수있는 방법은 다음과 같습니다. 할당의 첫 번째 인스턴스는 제로 패딩을 생성하므로이를 제로 패딩 및 상대 패딩 모두에 사용할 수 있습니다 (원래 배열의 가장자리 값을 패딩 된 배열로 복사하는 곳입니다).

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의 패드 방법입니다. 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%

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의 다른 입력 파이프 라인 기능과 동일하게 작동하며 기계 학습 애플리케이션에서 훨씬 더 잘 작동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.