2014-04-10 21 views
10

Novità in Python e Numpy, cercando di creare matrici tridimensionali. Il mio problema è che l'ordine delle dimensioni è spento rispetto a Matlab. In realtà l'ordine non ha alcun senso.Serie tridimensionale in numpy

Creazione di una matrice:

x = np.zeros((2,3,4)) 

Nel mio mondo ciò dovrebbe comportare 2 righe, 3 colonne e 4 dimensioni di profondità e dovrebbe essere presentata come:

[0 0 0  [0 0 0  [0 0 0  [0 0 0 
0 0 0]  0 0 0]  0 0 0]  0 0 0] 

Seperating su ogni dimensione di profondità . Invece è presentato come

[0 0 0 0  [0 0 0 0 
0 0 0 0  0 0 0 0 
0 0 0 0]  0 0 0 0] 

Cioè, 3 righe, 4 colonne e 2 dimensioni di profondità. Cioè, la prima dimensione è la "profondità". Per aggiungere ulteriore a questo problema, importando un'immagine con OpenCV la dimensione del colore è l'ultima dimensione, cioè, vedo le informazioni sul colore come la dimensione della profondità. Ciò complica notevolmente le cose se tutto ciò che voglio fare è provare qualcosa su un array tridimensionale più piccolo conosciuto.

Ho frainteso qualcosa? In caso contrario, perché diamine è numpy usando un modo così poco intuitivo di lavorare con array 3D dimensionali?

risposta

7

Hai ragione, stai creando una matrice con 2 righe, 3 colonne e 4 profondità. stampe NumPy matrici diverse per Matlab:

NumPy:

>>> import numpy as np 
>>> np.zeros((2,3,2)) 
array([[[ 0., 0.], 
    [ 0., 0.], 
    [ 0., 0.]], 

    [[ 0., 0.], 
    [ 0., 0.], 
    [ 0., 0.]]]) 

Matlab

>> zeros(2, 3, 2) 
ans(:,:,1) = 
    0  0  0 
    0  0  0 
ans(:,:,2) = 
    0  0  0 
    0  0  0 

Tuttavia si sta calcolando la stessa matrice. Dai uno sguardo a Numpy for Matlab users, ti guiderà nella conversione del codice Matlab in Numpy.


Per esempio, se si sta utilizzando OpenCV, si può costruire un'immagine utilizzando NumPy tenendo conto che OpenCV utilizza BGR rappresentazione:

import cv2 
import numpy as np 

a = np.zeros((100, 100,3)) 
a[:,:,0] = 255 

b = np.zeros((100, 100,3)) 
b[:,:,1] = 255 

c = np.zeros((100, 200,3)) 
c[:,:,2] = 255 

img = np.vstack((c, np.hstack((a, b)))) 

cv2.imshow('image', img) 
cv2.waitKey(0) 

enter image description here

Se si dà un'occhiata alla matrice c vedrai che è una matrice 100x200x3 che è esattamente ciò che viene mostrato nell'immagine (in rosso dato che abbiamo impostato la coordinata R su 255 e gli altri due rimangono su 0).

+0

OK, quindi se tutto è calcolato correttamente, posso prevedere che un algoritmo sia lo stesso sia per le matrici più piccole sia per le immagini di grandi dimensioni? Trattare la terza dimensione come "profondità". Il che ha senso dal momento che i calcoli trattano tutte le dimensioni allo stesso modo. Ma c'è un modo per rendere Numpy presente correttamente? Temo che il collegamento non abbia aiutato molto a riguardo :( – Vejto

+0

Matlab e Numpy non trattano le immagini allo stesso modo, se si utilizza OpenCV quindi rappresenta le immagini come BGR anziché RGB, quindi Matlab legge la matrice utilizzando fortran. Quindi devi tener conto di tutte queste cose quando fai il porting del codice da matlab a numpy – jabaldonedo

+0

Ottimo, ho provato alcune cose ed è, ovviamente, come dici tu. Sono a conoscenza della presentazione di BGR (mi infastidisce ma non tanto quanto.) Ho solo desiderato che ci fosse un modo per presentarlo "correttamente". Per ora, guarderò ogni singolo da meno separatamente (per una matrice 3D e) e [:,:, 1] viene visualizzato correttamente mentre e [:,::: 1] viene visualizzato illogico Grazie! – Vejto

11

Si dispone di una rappresentazione di array troncata. Diamo un'occhiata a pieno esempio:

>>> a = np.zeros((2, 3, 4)) 
>>> a 
array([[[ 0., 0., 0., 0.], 
     [ 0., 0., 0., 0.], 
     [ 0., 0., 0., 0.]], 

     [[ 0., 0., 0., 0.], 
     [ 0., 0., 0., 0.], 
     [ 0., 0., 0., 0.]]]) 

array in NumPy vengono stampati come parola array seguita dalla struttura, simile alle liste Python embedded. Creiamo elenco simile:

>>> l = [[[ 0., 0., 0., 0.], 
      [ 0., 0., 0., 0.], 
      [ 0., 0., 0., 0.]], 

      [[ 0., 0., 0., 0.], 
      [ 0., 0., 0., 0.], 
      [ 0., 0., 0., 0.]]] 

>>> l 
[[[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]], 
[[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]] 

primo livello di questo elenco composto l ha esattamente 2 elementi, proprio come prima dimensione dell'array a (# di righe). Ognuno di questi elementi è di per sé elenco con 3 elementi, che è uguale alla seconda dimensione di a (numero di colonne). Infine, gli elenchi più annidati hanno 4 elementi ciascuno, come la terza dimensione di a (profondità/numero di colori).

Quindi hai esattamente la stessa struttura (in termini di dimensioni) come in Matlab, appena stampato in altro modo.

Alcuni avvertimenti.

  1. Matlab colonna memorizza dati per colonna ("ordine Fortran"), mentre NumPy da archivi predefiniti loro riga per riga ("ordine C"). Ciò non influisce sull'indicizzazione, ma può influire sulle prestazioni. Ad esempio, in Matlab il ciclo efficiente si sovrapporrà alle colonne (ad esempio for n = 1:10 a(:, n) end), mentre in NumPy è preferibile iterare su righe (ad esempio for n in range(10): a[n, :] - nota n in prima posizione, non l'ultima).

  2. Se si lavora con immagini a colori in OpenCV, ricordate che:

    2.1. Memorizza le immagini in formato BGR e non RGB, come fa la maggior parte delle librerie Python.

    2.2. La maggior parte delle funzioni funziona sulle coordinate dell'immagine (x, y), che sono opposte alle coordinate matriciali (i, j).

+0

Sì, ho capito molto da jabaldonedo e alcuni test. Illogico in come viene visualizzato anche se la logica backend lo rende più comprensibile. lo stoccaggio dell'ordine, ottimo suggerimento! – Vejto

+2

Non lo è in realtà illogico, è solo diverso. Non esiste un modo reale per rappresentare la matrice 3D sullo schermo 2D, quindi ambienti diversi utilizzano approcci diversi. Ed entrambi - Matlab e NumPy - hanno le loro motivazioni per stampare array come fanno. – ffriend

+0

dopo aver letto questa risposta e averla gettato via, mi sembra di pensare che gli array numpy nella sequenza "riga, colonna, pila" non siano appropriati. È meglio pensare, "un primo contenitore contenente un secondo contenitore contenente un secondo contenitore". –