web-dev-qa-db-fra.com

Ajouter des dimensions à un tableau Numpy

Je commence avec un tableau numpy d'une image.

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

La forme correspond à ce à quoi vous pourriez vous attendre pour une image RVB 640x480.

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

Cependant, cette image que je possède est une image d'une vidéo de 100 images. Idéalement, j'aimerais disposer d'un seul tableau contenant toutes les données de cette vidéo, de sorte que img.shape résultats (480, 640, 3, 100).

Quel est le meilleur moyen d'ajouter la trame suivante (c'est-à-dire l'ensemble de données d'image suivant, un autre tableau de 480 x 640 x 3) à mon tableau initial?

45
Chris

Vous demandez comment ajouter une dimension à un tableau NumPy, de sorte que cette dimension puisse ensuite être développée pour accueillir de nouvelles données. Une dimension peut être ajoutée comme suit:

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

47
dbliss

Alternativement à

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

dans @ dbliss 'answer , vous pouvez également utiliser numpy.expand_dims comme

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

Par exemple (tiré du lien ci-dessus):

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

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

Ensuite

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

les rendements

array([[1, 2]])

et

y.shape

donne

(1, 2)
31
Cleb

Vous pouvez simplement créer un tableau de la bonne taille et le remplir:

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

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

si les cadres étaient des fichiers jpg individuels nommés d’une manière particulière (dans l’exemple, frame_0.jpg, frame_1.jpg, etc.).

Juste une note, vous pourriez envisager d'utiliser un (nframes, 480,640,3) en forme de tableau, à la place.

19
JoshAdel

Vous pouvez utiliser np.concatenate() pour spécifier le axis à ajouter, à l'aide de np.newaxis:

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

Si vous lisez de nombreux fichiers:

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

Aucune structure dans numpy ne vous permet d'ajouter plus de données ultérieurement.

Au lieu de cela, numpy place toutes vos données dans un bloc de nombres contigus (essentiellement un tableau C), et tout redimensionnement nécessite d'allouer un nouveau bloc de mémoire pour le contenir. La rapidité de Numpy est de pouvoir conserver toutes les données d’un tableau numpy dans le même bloc de mémoire; par exemple. les opérations mathématiques peuvent être parallélisées pour la vitesse et vous obtenez moins erreurs de cache .

Donc, vous aurez deux types de solutions:

  1. Préallouez la mémoire pour le tableau numpy et remplissez les valeurs, comme dans la réponse de JoshAdel, ou
  2. Conservez vos données dans une liste normale python) jusqu'à ce que vous ayez réellement besoin de les rassembler (voir ci-dessous).

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

Notez qu'il n'est pas nécessaire d'étendre les dimensions des tableaux d'images individuels en premier, ni de savoir combien d'images vous attendez à l'avance.

2
Multihunter

J'ai suivi cette approche:

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).
1
richar8086

Considérez l’approche 1 avec la méthode reshape et l’approche 2 avec la méthode np.newaxis qui produisent le même résultat:

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

Nous avons comme résultat:

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]]]]
0
Roman