2013-06-30 42 views
19

Iniziamo con una serie numerica di un'immagine.Aggiungere dimensioni a un array Numpy

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

La forma è ciò che ci si potrebbe aspettare per un'immagine RGB 640x480.

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

Tuttavia, questa immagine che ho è una cornice di un video, che è lunga 100 fotogrammi. Idealmente, mi piacerebbe avere un singolo array che contenga tutti i dati di questo video in modo tale che img.shape restituisca (480, 640, 3, 100).

Qual è il modo migliore per aggiungere il fotogramma successivo, ovvero il prossimo insieme di dati di immagine, un altro array 480 x 640 x 3, al mio array iniziale?

risposta

10

Si potrebbe semplicemente creare un array di dimensioni corrette up-front e riempirlo:

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

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

se i fotogrammi sono stati singolo file jpg che sono stati nominati in qualche modo particolare (nell'esempio, frame_0.jpg , frame_1.jpg, ecc.).

Solo una nota, si potrebbe considerare l'utilizzo di una matrice a forma di (nframes, 480,640,3), invece.

+0

Penso che questa sia la strada da percorrere. se usi la concatenazione dovrai spostare la matrice in memoria ogni volta che la aggiungi. per 100 frame che non dovrebbero avere importanza, ma se vuoi andare a video più grandi. A proposito, avrei usato il numero di fotogrammi come prima dimensione, quindi ho un array (100,480,640,3) in questo modo puoi accedere ai singoli fotogrammi (cosa vuoi che di solito vuoi vedere, giusto?) Più semplice (F [1] ] invece di F [:,:,:, 1]). Ovviamente, per quanto riguarda le prestazioni, non dovrebbe importare nulla. – Magellan88

3

È possibile utilizzare np.concatenate() specificando quali axis da aggiungere, utilizzando np.newaxis:

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

Se state leggendo da molti file:

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

Ti stai chiedendo come aggiungere una dimensione a un Array NumPy, in modo che tale dimensione possa essere ampliata per accogliere nuovi dati. Una dimensione può essere aggiunta come segue:

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

+2

Attualmente, 'numpy.newaxis' è definito come' None' (nel file 'numeric.py'), quindi in modo equivalente si potrebbe usare' image = image [..., None]. – Ray

0

Ho seguito questo approccio:

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). 
3

alternativa a

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

in risposta @dbliss', è anche possibile utilizzare numpy.expand_dims come

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

Per esempio (tratto dal link sopra):

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

print x.shape # prints (2,) 

Poi

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

cede

array([[1, 2]]) 

e

y.shape 

(1, 2) 
+0

come aggiungere valori nella nuova dimensione? se faccio 'y [1,0]' dà un errore di indice fuori dai limiti. 'y [0,1]' è accessibile – weima

+0

@weima: Non sei completamente sicuro di cosa stai cercando. Qual è il tuo output desiderato? – Cleb

0

Non esiste una struttura in numpy che consente di aggiungere più dati in un secondo momento.

Invece, numpy inserisce tutti i dati in una porzione contigua di numeri (in pratica, un array C) e qualsiasi ridimensionamento richiede l'allocazione di un nuovo blocco di memoria per trattenerlo. La velocità di Numpy deriva dall'essere in grado di mantenere tutti i dati in una serie numpy nella stessa porzione di memoria; per esempio. le operazioni matematiche possono essere parallelized for speed e si ottiene meno cache misses.

Quindi si avranno due tipi di soluzioni:

  1. pre-allocare la memoria per la matrice NumPy e compilare i valori, come nella risposta di JoshAdel, o
  2. Conservare i dati in un pitone normale elenco fino in realtà è necessario per metterli tutti insieme (vedi sotto)

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

Si noti che non è necessario espandere prima le dimensioni dei singoli array di immagini, né è necessario sapere quante immagini ci si aspetta prima del tempo.