2010-11-20 21 views
5

Sono un laureato in scienze all'università che lavora su un progetto di programmazione per il mio corso Calc III che comporta la decomposizione a valore singolare. L'idea è fondamentalmente di convertire un'immagine di m x n dimensioni in una matrice m x n in cui ogni elemento è una tupla che rappresenta i canali di colore (r, g, b) del pixel nel punto (m, n). Sto usando Python perché è l'unica lingua che ho davvero insegnato finora.Python - NumPy - tuple come elementi di un array

Da quello che posso dire, Python generalmente non ama le tuple come elementi di un array. Ho fatto una piccola ricerca di mio e ho trovato una soluzione, vale a dire, pre-allocare l'array come segue:

def image_to_array(): #converts an image to an array 
    aPic = loadPicture("zorak_color.gif") 
    ph = getHeight(aPic) 
    pw = getWidth(aPic) 
    anArray = zeros((ph,pw), dtype='O') 
    for h in range(ph): 
     for w in range(pw):    
      p = getPixel(aPic, w, h) 
      anArray[h][w] = (getRGB(p)) 
    return anArray 

questo ha funzionato correttamente per la prima parte del compito, che era semplicemente quello di convertire un'immagine in un matrice (non è coinvolta algebra lineare).

La parte con SVD, tuttavia, è dove diventa più complicato. Quando io chiamo la funzione built-in NumPy SVD, utilizzando la matrice ho costruito dalla mia immagine (in cui ogni elemento è una tupla), ottengo il seguente errore:

Traceback (most recent call last): 
    File "<pyshell#5>", line 1, in -toplevel- 
    svd(x) 
    File "C:\Python24\Lib\site-packages\numpy\linalg\linalg.py", line 724, in svd 
    a = _fastCopyAndTranspose(t, a) 
    File "C:\Python24\Lib\site-packages\numpy\linalg\linalg.py", line 107, in _fastCopyAndTranspose 
    cast_arrays = cast_arrays + (_fastCT(a.astype(type)),) 
ValueError: setting an array element with a sequence. 

Questo è lo stesso errore mi è stato sempre inizialmente , prima ho fatto qualche ricerca e ho scoperto che potevo pre-allocare i miei array per consentire le tuple come elementi.

Il problema ora è che sono solo nel mio primo semestre di programmazione (livello universitario), e queste funzioni numpy scritte da e per programmatori professionisti sono un po 'troppo black-box per me (anche se sono sicuro che sono molto più chiari a quelli con esperienza). Quindi modificare queste funzioni per consentire le tuple è un po 'più complicato di quando l'ho fatto sulla mia funzione. Dove devo andare da qui? Suppongo che dovrei copiare le funzioni numPy rilevanti nel mio programma e modificarle di conseguenza?

Grazie in anticipo.

+3

L'SVD funziona solo su matrici. Hai intenzione di fare un SVD per ciascuno dei canali RGB? In altre parole, anche se si forma un array m x n x 3, non è possibile passarlo alla funzione SVD perché gli SVD sono definiti per matrici non tensori di dimensioni arbitrarie. –

risposta

2

Penso che vogliate un ph entro il pw entro il 3 array numpy.

anArray = zeros((ph,pw,3)) 
for h in range(ph): 
    for w in range(pw):    
     p = getPixel(aPic, w, h) 
     anArray[h][w] = getRGB(p) 

Hai solo bisogno di assicurarsi che getRGB restituisce un elenco di 3 elementi, invece di una tupla.

+0

Certo, è stato abbastanza facile, ho appena messo list() su getRGB. Ma dopo aver seguito le tue modifiche, ho iniziato a ricevere un nuovo errore: File "C: \ Python24 \ Lib \ site-packages \ numpy \ linalg \ linalg.py", riga 720, in svd _assertRank2 (a) File " C: \ Python24 \ Lib \ site-packages \ numpy \ linalg \ linalg.py ", riga 116, in _assertRank2 raise LinAlgError, '% d-dimensional array data. Array deve essere \ LinAlgError: array a 3 dimensioni dato. Array deve essere bidimensionale quindi ho ancora bisogno di un modo per avere una matrice "2-d" di tuple che funzionerà con numPy ... – Thomas

+0

A pensarci bene, questo non ha davvero senso. Non penso che tu possa trovare l'SVD di una matrice 2D le cui voci sono tuple, e se esiste una cosa come SVD di una matrice 3D, è decisamente al di fuori della portata della mia classe e del progetto. Ho bisogno di capire come fare questo per ogni canale di colore e quindi combinare quelle tre matrici in qualche modo. Grazie per la risposta. – Thomas

+0

C'è * una * versione 3D di SVD [DeLathauwer 2000] [Mesgarani 2004], ma sospetto che non sia quello che vuoi. Per un'attività come il riconoscimento facciale, le persone spesso vettorializzano * intere immagini *, quindi concatenano questi vettori in una grande dimensione 'X' di matrice (h * w) -by- (num immagini), * quindi * eseguono PCA su' X 'che è equivalente a SVD di' XX^T'. Ho risposto a una domanda correlata qui: http://stackoverflow.com/questions/4171866/creating-a-dataset-from-an-image-with-python-for-face-recognition/4176400#4176400 –

7

Invece di impostare il tipo di elemento di matrice su "O" (oggetto), è necessario impostarlo su una tupla. Vedi the SciPy manual per alcuni esempi.

Nel tuo caso, più semplice è quello di utilizzare qualcosa come

a = zeros((ph,pw), dtype=(float,3)) 

Assumendo che il valori RGB sono tuple di 3 numeri in virgola mobile.

Questo è simile alla creazione di una matrice 3d (come Steve suggerito) e, infatti, gli elementi della tupla sono accessibili come a[n,m][k] o z[n,m,k] dove k è l'elemento nella tupla.

Ovviamente, l'SVD è definito per matrici 2D e non per matrici 3D, quindi non è possibile utilizzare linalg.svd (a). Devi decidere SVD di quale matrice (dei tre possibili: R G e B) di cui hai bisogno.

Se, ad esempio, si desidera che lo SVD della matrice "R" (partendo dal presupposto che è il primo elemento della tupla) usare qualcosa come:

linalg.svd(a[:,:,1]) 
Problemi correlati