Numpy 배열에 새 차원을 추가하려면 어떻게해야합니까?


85

나는 이미지의 numpy 배열로 시작합니다.

In[1]:img = cv2.imread('test.jpg')

모양은 640x480 RGB 이미지에 대해 예상 할 수있는 것입니다.

In[2]:img.shape
Out[2]: (480, 640, 3)

하지만 제가 가지고있는이 이미지는 100 프레임 길이의 비디오 프레임입니다. 이상적으로, 나는 그런 것을이 비디오에서 모든 데이터를 포함하는 단일 배열하고 싶은 img.shape반환 (480, 640, 3, 100).

다음 프레임, 즉 다음 이미지 데이터 세트, 또 다른 480 x 640 x 3 어레이를 초기 어레이에 추가하는 가장 좋은 방법은 무엇입니까?

답변:


98

NumPy 배열에 차원을 추가하는 방법을 묻습니다. 그러면 해당 차원이 새 데이터를 수용하도록 확장 될 수 있습니다. 차원은 다음과 같이 추가 할 수 있습니다.

image = image[..., np.newaxis]

10
현재 numpy.newaxisNone(파일에 numeric.py) 로 정의되어 있으므로 동등하게`image = image [..., None]을 사용할 수 있습니다.
Ray

58
사용하지 마십시오 None. np.newaxis명시적인 것이 암시적인 것보다 낫기 때문에 사용하십시오 .
Neil G

7
어떻게 그렇게 될수 있니? None아무 의미도 없습니다. 명시 적입니다. 입니다 None. 명확하게 설명합니다. None 이다 것은 파이썬한다. 의심의 여지가 없습니다. None마지막 세부 사항입니다. 더 깊이 들어갈 수 없습니다. 반면에, numpy.newaxis의미한다 None. 본질적으로 None. 입니다 None. 그러나 None암시 적으로입니다. None직접 표현되지 는 않습니다 None. 명확하고 상세하게 명시 되어 혼란이나 의심의 여지가 없습니다. 직접 표현되지는 않지만 암시 적 제안. API 관점에서를 사용하는 것이 더 안전하다는 점을 추가해야합니다 numpy.newaxis.
Pedro Rodrigues 19

2
여기에서 명시 적이라는 것은 구문 적 / 의미 적 명확성이 아니라 "코더 의도"를 의미합니다.
Gabrer

이 경우 JoshAdel의 답변이 정답으로 선택되어야하며 더 많은 표가 필요합니다. 그의 요점은 OP가 더 높은 차원의 nparray에 추가하려고한다는 점에서 중요합니다. ndarray는 생성 된 후에는 크기를 늘릴 수 없으며 복사본을 만들어야합니다. 이 대답은 모양 (480, 640, 3, 1) 만 만들고 새 프레임을 추가 할 때마다 다른 복사본을 만듭니다. 안좋다.
Dan Boschen

59

또는

image = image[..., np.newaxis]

@dbliss '대답 , 당신은 또한 사용할 수 있습니다 numpy.expand_dims처럼

image = np.expand_dims(image, <your desired dimension>)

예 (위 링크에서 가져옴) :

x = np.array([1, 2])

print(x.shape)  # prints (2,)

그때

y = np.expand_dims(x, axis=0)

수확량

array([[1, 2]])

y.shape

준다

(1, 2)

새로운 차원에 값을 추가하는 방법은 무엇입니까? 내가 할 y[1,0]경우 인덱스 범위를 벗어난 오류가 발생합니다. y[0,1]액세스
WEIMA는

@weima : 당신이 무엇을 추구하는지 완전히 확신하지 못합니다. 원하는 출력은 무엇입니까?
Cleb

24

올바른 크기의 배열을 미리 만들어 채울 수 있습니다.

frames = np.empty((480, 640, 3, 100))

for k in xrange(nframes):
    frames[:,:,:,k] = cv2.imread('frame_{}.jpg'.format(k))

프레임이 특정 방식으로 이름이 지정된 개별 jpg 파일 인 경우 (예 : frame_0.jpg, frame_1.jpg 등).

참고로 (nframes, 480,640,3), 대신 모양 배열을 사용하는 것을 고려할 수 있습니다 .


1
이것이 갈 길이라고 생각합니다. 연결을 사용하는 경우 배열을 추가 할 때마다 메모리에서 배열을 이동해야합니다. 전혀 중요하지 않지만 더 큰 비디오로 이동하려는 경우 100 프레임. BTW, 프레임 수를 첫 번째 차원으로 사용 했으므로 개별 프레임에 액세스 할 수있는 (100,480,640,3) 배열을 사용합니다 (보통보고 싶은 것이 무엇입니까?) 더 쉽게 (F [1 ] 대신 F [:, :, :, 1]). 물론 성능면에서는 전혀 문제가되지 않습니다.
Magellan88 2014

저는 JoshAdel과 Magellan88에 동의합니다. 다른 답변은 메모리 현명하고 처리 시간이 매우 비효율적입니다. ndarray는 일단 생성되면 크기를 늘릴 수 없으므로 추가한다고 생각하면 항상 복사본이 만들어집니다.
Dan Boschen

10

Pythonic

X = X[:, :, None]

이는

X = X[:, :, numpy.newaxis]X = numpy.expand_dims(X, axis=-1)

그러나 이미지 스택에 대해 명시 적으로 질문 하고 있으므로 루프에서 수집 한 list이미지 를 스택하는 것이 좋습니다 np.stack([X1, X2, X3]).

치수 순서가 마음에 들지 않으면 재정렬 할 수 있습니다. np.transpose()


6

다음을 사용 np.concatenate()하여 axis추가 할 항목 을 지정할 수 있습니다 np.newaxis.

import numpy as np
movie = np.concatenate((img1[:,np.newaxis], img2[:,np.newaxis]), axis=3)

여러 파일에서 읽는 경우 :

import glob
movie = np.concatenate([cv2.imread(p)[:,np.newaxis] for p in glob.glob('*.jpg')], axis=3)

2

numpy에는 나중에 더 많은 데이터를 추가 할 수있는 구조가 없습니다.

대신 numpy는 모든 데이터를 연속 된 숫자 청크 (기본적으로 C 배열)에 넣고 크기를 조정하려면 데이터를 저장할 새 메모리 청크를 할당해야합니다. Numpy의 속도는 동일한 메모리 청크에있는 numpy 배열의 모든 데이터를 유지할 수 있다는 점에서 비롯됩니다. 예를 들어 수학적 연산은 속도 를 위해 병렬화 될 수 있으며 캐시 미스 가 줄어 듭니다 .

따라서 두 가지 종류의 솔루션이 있습니다.

  1. numpy 배열에 대한 메모리를 미리 할당하고 JoshAdel의 답변과 같이 값을 입력하거나
  2. 데이터를 실제로 모두 합쳐야 할 때까지 일반 파이썬 목록에 보관하십시오 (아래 참조).

images = []
for i in range(100):
    new_image = # pull image from somewhere
    images.append(new_image)
images = np.stack(images, axis=3)

먼저 개별 이미지 배열의 차원을 확장 할 필요가 없으며 예상되는 이미지 수를 미리 알 필요도 없습니다.


2

reshape 방법을 사용하는 접근법 1과 동일한 결과를 생성하는 np.newaxis 방법을 사용하는 접근법 2를 고려하십시오.

#Lets suppose, we have:
x = [1,2,3,4,5,6,7,8,9]
print('I. x',x)

xNpArr = np.array(x)
print('II. xNpArr',xNpArr)
print('III. xNpArr', xNpArr.shape)

xNpArr_3x3 = xNpArr.reshape((3,3))
print('IV. xNpArr_3x3.shape', xNpArr_3x3.shape)
print('V. xNpArr_3x3', xNpArr_3x3)

#Approach 1 with reshape method
xNpArrRs_1x3x3x1 = xNpArr_3x3.reshape((1,3,3,1))
print('VI. xNpArrRs_1x3x3x1.shape', xNpArrRs_1x3x3x1.shape)
print('VII. xNpArrRs_1x3x3x1', xNpArrRs_1x3x3x1)

#Approach 2 with np.newaxis method
xNpArrNa_1x3x3x1 = xNpArr_3x3[np.newaxis, ..., np.newaxis]
print('VIII. xNpArrNa_1x3x3x1.shape', xNpArrNa_1x3x3x1.shape)
print('IX. xNpArrNa_1x3x3x1', xNpArrNa_1x3x3x1)

결과는 다음과 같습니다.

I. x [1, 2, 3, 4, 5, 6, 7, 8, 9]

II. xNpArr [1 2 3 4 5 6 7 8 9]

III. xNpArr (9,)

IV. xNpArr_3x3.shape (3, 3)

V. xNpArr_3x3 [[1 2 3]
 [4 5 6]
 [7 8 9]]

VI. xNpArrRs_1x3x3x1.shape (1, 3, 3, 1)

VII. xNpArrRs_1x3x3x1 [[[[1]
   [2]
   [3]]

  [[4]
   [5]
   [6]]

  [[7]
   [8]
   [9]]]]

VIII. xNpArrNa_1x3x3x1.shape (1, 3, 3, 1)

IX. xNpArrNa_1x3x3x1 [[[[1]
   [2]
   [3]]

  [[4]
   [5]
   [6]]

  [[7]
   [8]
   [9]]]]

1

이 접근 방식을 따랐습니다.

import numpy as np
import cv2

ls = []

for image in image_paths:
    ls.append(cv2.imread('test.jpg'))

img_np = np.array(ls) # shape (100, 480, 640, 3)
img_np = np.rollaxis(img_np, 0, 4) # shape (480, 640, 3, 100).
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.