2010-11-20 7 views
5

Ich bin ein CS-Major in der Universität, der an einem Programmierprojekt für meinen Calc III-Kurs mit Singulärwertzerlegung arbeitet. Die Idee besteht im Wesentlichen darin, ein Bild von m × n Dimensionen in eine m × n Matrix umzuwandeln, wobei jedes Element ein Tupel ist, das die Farbkanäle (r, g, b) des Pixels am Punkt (m, n) darstellt. Ich benutze Python, weil es die einzige Sprache ist, die ich bisher (gut) gelernt habe.Python - NumPy - Tupel als Elemente eines Arrays

Von dem, was ich sagen kann, mag Python Tupel im Allgemeinen nicht als Elemente eines Arrays. Ich habe eine wenig Forschung meines eigenen und eine Abhilfe gefunden, nämlich das Array vor der Zuteilung wie folgt:

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 

Dies korrekt zum ersten Teil der Aufgabe gearbeitet, die einfach ein Bild ein konvertieren waren Matrix (keine lineare Algebra beteiligt).

Der Teil mit SVD ist jedoch, wo es schwieriger wird. Wenn ich rufe die eingebauten in numpy SVD-Funktion, die Array ich von meinem Bild aufgebaut (wobei jedes Element ein Tupel), erhalte ich folgende Fehlermeldung:

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. 

Dies ist der gleiche Fehler war ich immer am Anfang , bevor ich etwas recherchiert habe und festgestellt habe, dass ich meine Arrays vorbelegen könnte, um Tupel als Elemente zuzulassen.

Das Problem ist jetzt, dass ich nur in meinem ersten Semester (College-Level) -Programmierung bin, und diese Anzahl Funktionen von und für professionelle Programmierer sind ein wenig zu Black-Box für mich (obwohl ich sicher bin sind für diejenigen mit Erfahrung viel klarer. Die Bearbeitung dieser Funktionen für Tupel ist etwas komplizierter als bei meiner eigenen Funktion. Wohin muss ich von hier gehen? Ich nehme an, ich sollte die entsprechenden numPy-Funktionen in mein eigenes Programm kopieren und entsprechend ändern.

Vielen Dank im Voraus.

+3

Die SVD nur auf Matrizen funktioniert. Planen Sie eine SVD für jeden der RGB-Kanäle? Mit anderen Worten, selbst wenn Sie ein m x n x 3-Array bilden, können Sie das nicht einfach an die SVD-Funktion übergeben, da SVDs für Matrizen nicht beliebig große Tensoren definiert sind. –

Antwort

2

Ich denke, Sie wollen eine ph von pw von 3 numpy Array.

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) 

Sie müssen nur sicherstellen, dass getRGB gibt eine 3-Element-Liste anstelle eines Tupels.

+0

Sicher, das war einfach genug, ich habe nur liste() um getRGB gesetzt. Aber nachdem ich Ihren Änderungen gefolgt bin, habe ich einen neuen Fehler bekommen: Datei "C: \ Python24 \ Lib \ site-Pakete \ numpy \ linalg \ linalg.py", Zeile 720, in svd _assertrank2 (a) Datei " C: \ Python24 \ Lib \ Site-Pakete \ numpy \ linalg \ linalg.py ", Zeile 116, in _assertrank2 raise LinAlgError, '% d-dimensionales Array gegeben. Array muss \ sein \ LinAlgError: 3-dimensionale Array gegeben. Array muss zweidimensional sein also brauche ich noch eine Möglichkeit, eine "2-d" Matrix von Tupeln, die mit numPy funktioniert ... – Thomas

+0

Auf den zweiten Gedanken, das macht nicht wirklich Sinn. Ich glaube nicht, dass Sie die SVD einer 2D-Matrix finden, deren Einträge Tupel sind, und wenn es so etwas wie SVD einer 3D-Matrix gibt, ist das definitiv außerhalb des Rahmens meiner Klasse und dieses Projekts. Ich muss herausfinden, wie man das für jeden Farbkanal macht und dann diese drei Matrizen irgendwie kombiniert. Danke für die Antwort. – Thomas

+0

Es gibt * eine 3D-Version von SVD [DeLathauwer 2000] [Mesgarani 2004], aber ich vermute, dass es nicht das ist, was Sie wollen. Für eine Aufgabe, wie die Gesichtserkennung, vektorisieren Leute häufig * ganze Bilder *, verketten dann diese Vektoren in eine große Matrix "X" der Größe (h * w) -durch- (Anzahl Bilder), * führen dann PCA auf 'X durch 'was entspricht der SVD von' XX^T'. Ich beantwortete eine verwandte Frage hier: http://stackoverflow.com/questions/4171866/creating-a-dataset-from-an-image-with-python-for-face-recognition/4176400#4176400 –

7

Anstatt den Array-Elementtyp auf 'O' (Objekt) zu setzen, sollten Sie ihn auf ein Tupel setzen. Einige Beispiele finden Sie unter .

In Ihrem Fall ist am einfachsten, so etwas wie

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

Angenommen, Ihre RGB-Werte sind Tupeln von 3 Gleitkommazahlen zu verwenden.

Dies ist ähnlich einem 3D-Array zu schaffen (wie Steve vorgeschlagen), und in der Tat sind die Elemente Tupel zugegriffen als a[n,m][k] oder z[n,m,k] wo k das Element in dem Tupel ist.

Natürlich ist die SVD für 2D-Matrizen und nicht für 3D-Arrays definiert, so dass Sie linalg.svd (a) nicht verwenden können. Sie müssen SVD entscheiden, welche Matrix (von den drei möglichen: R G und B) Sie benötigen.

Wenn Sie zum Beispiel des SVD der „R“ Matrix will (unter der Annahme, dass das erste Element des Tupels ist) verwenden, so etwas wie:

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