2013-11-20 8 views
6

Ich versuche eine effiziente Möglichkeit zu finden, von einem Tupel (wo alle 4 Einträge R, G, B, Alpha eines Pixels entsprechen) zu einem NumPy-Array zu konvertieren (zur Verwendung in OpenCV).NumPy - Effiziente Konvertierung von Tupel zu Array?

Genauer gesagt, ich benutze pywin32, um die Client-Bereich Bitmap eines Fensters zu erhalten. Dies wird in Form eines Tupels zurückgegeben, wobei die ersten vier Elemente zu den RGB-Alpha-Kanälen des ersten Pixels gehören, dann die nächsten vier des zweiten Pixels und so weiter. Das Tupel selbst enthält nur die ganzzahligen Daten (d. H. Es enthält keine Dimensionalität, obwohl ich diese Information habe). Aus diesem Tupel möchte ich ein NumPy 3D-Array erstellen (Breite x Höhe x Kanal). Momentan erstelle ich einfach ein Array von Nullen, gehe dann durch jeden Eintrag im Tupel und platziere ihn im NumPy-Array. Ich mache das mit dem unten stehenden Code. Und ich hoffe, dass es einen wesentlich effizienteren Weg gibt, an den ich gerade nicht denke. Irgendwelche Vorschläge? Vielen Dank!

Code:

bitmapBits = dataBitmap.GetBitmapBits(False) #Gets the tuple. 
clientImage = numpy.zeros((height, width, 4), numpy.uint8) 
iter_channel = 0 
iter_x = 0 
iter_y = 0 
for bit in bitmapBits: 
    clientImage[iter_y, iter_x, iter_channel] = bit 
    iter_channel += 1 
    if iter_channel == 4: 
     iter_channel = 0 
     iter_x += 1 
    if iter_x == width: 
     iter_x = 0 
     iter_y += 1 
    if iter_y == height: 
     iter_y = 0 

Antwort

5

Ähnlich wie Bill oben, aber wahrscheinlich noch schneller:

array nimmt, entsprechend der Dokumentation: "Ein Array, jedes Objekt, das die Array-Schnittstelle aussetzt, ein Objekt, dessen __array__ Methode gibt ein Array oder eine beliebige (verschachtelte) Sequenz zurück. "

asarray braucht ein paar weitere Dinge: "Eingabedaten, in jeder Form, die in ein Array konvertiert werden kann. Dazu gehören Listen, Listen von Tupeln, Tupel, Tupel von Tupeln, Tupel von Listen und ndarrays." Es nimmt Tupel direkt :)

+0

Dies ist in der Tat etwas schneller (für meine aktuelle Verwendung ist es etwa 10% schneller als die von Bill vorgeschlagene Lösung). – golmschenk

5

Warum nicht einfach etwas tun, wie

import numpy as np 
clientImage = np.array(list(bitmapBits), np.uint8).reshape(height, width, 4) 

Zum Beispiel lassen ('Ri', 'Gi', 'Bi', 'ai') die Farbe Tupel seine entsprechenden i Pixel. Wenn Sie ein großes Tupel von diesen haben, können Sie tun:

In [9]: x = ['R1', 'G1', 'B1', 'a1', 'R2', 'G2', 'B2', 'a2', 'R3', 'G3', 'B3', 'a3', 'R4', 'G4', 'B4', 'a4'] 

In [10]: np.array(x).reshape(2, 2, 4) 
Out[10]: 
array([[['R1', 'G1', 'B1', 'a1'], 
     ['R2', 'G2', 'B2', 'a2']], 

     [['R3', 'G3', 'B3', 'a3'], 
     ['R4', 'G4', 'B4', 'a4']]], 
     dtype='|S2') 

Jede Scheibe [:,:,i] für i in [0,4) geben Ihnen jeden Kanal:

In [15]: np.array(x).reshape(2, 2, 4)[:,:,0] 
Out[15]: 
array([['R1', 'R2'], 
     ['R3', 'R4']], 
     dtype='|S2')