Image.fromstring: Wie muss der string aussehen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
tromai
User
Beiträge: 92
Registriert: Mittwoch 26. April 2006, 11:20

Hallo,

ich habe ein array mit 9 Integerwerten zwischen 0 und 255. Daraus möchte ich ein jpg mit Grauwerten (die eben diesen Values haben sollen) erzeugen. Mir schein es ist der beste Weg mit Image.fromstring zu arbeiten.

Der Array sieht folgendermaßen aus:

Code: Alles auswählen

[[1, 16, 32, 64, 80, 96, 102, 240, 13]]
Wie muss der String aussehen, damit dann auch wirklich mit dem Befehl

Code: Alles auswählen

Image.fromstring("L",(3,3),string)
ein entsprechendes Bild herauskommt.

Ich muss dazusagen, dass ich eher ein Pythonanfänger bin und mit PIL noch nicht gearbeitet habe.

Ich wäre für schnelle Hilfe sehr dankbar.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi,

was heißt, bitte schön, daß Du "ein array hast"? Ein Python array? numpy / scipy array?

Ein Beispiel mit Image und scipy:

Code: Alles auswählen

from scipy import array
from scipy.misc import toImage
import Image

l = [[1,2,3,4]]
a = array(l)

i = toImage(a)
i.save('test.jpg')
Wird natürlich nur funktionieren, wenn Du den jpeg encoder hast. Ansonsten mußt Du ein anderes Format verwenden.

Wenn Dir das nicht hilft, wäre es vielleicht gut, wenn Du etwas genauer sagen könntest was Dein array ist ( type(x) ) und wie Du es generierst.

Gruß,
Christian

PS Werde wohl bald nicht mehr antworten können, weil ich für die nächsten Tage abdampfe.
BlackJack

tromai hat geschrieben:Hallo,

ich habe ein array mit 9 Integerwerten zwischen 0 und 255. Daraus möchte ich ein jpg mit Grauwerten (die eben diesen Values haben sollen) erzeugen. Mir schein es ist der beste Weg mit Image.fromstring zu arbeiten.

Der Array sieht folgendermaßen aus:

Code: Alles auswählen

[[1, 16, 32, 64, 80, 96, 102, 240, 13]]
Wie muss der String aussehen, damit dann auch wirklich mit dem Befehl

Code: Alles auswählen

Image.fromstring("L",(3,3),string)
ein entsprechendes Bild herauskommt.
Zeichenketten in Python sind eigentlich Byteketten, dass heisst jedes Zeichen kann einen Wert von 0 bis 255 haben. Du musst die Zahlen in der Liste also einfach mit `chr()` in Zeichen umwandeln und diese zu einer Zeichenkette zusammensetzen:

Code: Alles auswählen

import Image
data = [1, 16, 32, 64, 80, 96, 102, 240, 13]
image = Image.fromstring('L', (3, 3), ''.join(map(chr, data)))
image.save('test.png')
Benutzeravatar
tromai
User
Beiträge: 92
Registriert: Mittwoch 26. April 2006, 11:20

@Blackjack:
Danke, das ist genau das was ich wissen wollte. Es funktioniert einwandfrei. ich hätte gleich noch eine Frage:

Ein Zeichen hat ja 8 bit. Für Greyscale-Bilder ist das ja kein Problem. Wie ist das wenn ich ein RGB-Bild erzeugen will. Die sind in der Regel ja 24 Bit kodiert. Gilt dann, dass 3 Zeichen einem Pixel zugeordnet werden? oder bedarf es da anderer Methoden?

Edit: Hat sich erledigt. Es ist natürlich so wie vermuted

Allerdings habe ich gleich nocht eine andere Frage zu dem Thema. Gibt es eine Möglichkeit aus einem array direkt ein Image-Objekt zu erstellen? Momentan habe ich ein array mit über 2 Mio Zeichen, das ich über ein join umständlich in ein String umwandle. Das dauert einfach zu lange. Das muss doch irgendwie schneller gehen. Ich suche schon eine ganze Weile, finde aber nichts. Vielleicht hat ja jemand einen Tip. Vielleicht gibt es ja auch Funktionen, die das gleiche wie join() machen aber schneller sind.
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

Vielleicht sollte man das mit C/C++ machen, ein anderes Tool als join kenne ich nicht (was aber ehrlich gesagt nichts heißen muss^^).
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Hi

Schau dir scipy an, wie schon CM gesagt hat. Das ist ziemlich schnell mit Arrays, damit kannst du wahrscheinlich deinen Array auch gleich generieren (falls er generiert ist, darüber hast du ja noch nichts geschrieben).

Gruss
BlackJack

tromai hat geschrieben:Gibt es eine Möglichkeit aus einem array direkt ein Image-Objekt zu erstellen? Momentan habe ich ein array mit über 2 Mio Zeichen, das ich über ein join umständlich in ein String umwandle. Das dauert einfach zu lange. Das muss doch irgendwie schneller gehen.
Erstmal: Bitte nenn' Listen nicht immer Arrays -- das ist verwirrend. Du könntest zum Beispiel wirklich ein `array` aus dem `array` Modul nehmen und darauf dann die `tostring()` Methode anwenden.

Oder Numpy Arrays. Das hängt letztendlich wirklich davon ab, wo Du die Daten herbekommst, bzw. wie Du sie erzeugst.
Benutzeravatar
tromai
User
Beiträge: 92
Registriert: Mittwoch 26. April 2006, 11:20

Ok, danke mal für die Tips (und für die Verbesserung (Liste - Array)). Das werde ich mal ausprobieren und dann berichten.
Benutzeravatar
tromai
User
Beiträge: 92
Registriert: Mittwoch 26. April 2006, 11:20

So, ich habe es jetzt getestet. Letztendlich habe ich auf CMs Lösung zurückgegriffen. Klappt wunderbar nachdem ich (und andere) mich mehrere Tage mit der Scipyinstallation herumgeschlagen habe.

Jetzt habe ich aber gleich noch eine Frage:
Wie bekomme ich das ganze in Farbe?
Mit dem Befehl:

Code: Alles auswählen

toimage(arr, high=255, low=0, cmin=None, cmax=None, pal=None, mode=None)
sollte das ja funktionieren. Allerdings ist mir nicht ganz klar, welchen Wert ich für "pal" und "mode" wählen muss.
"Mode" sollte P sein. Allerdings kann ich mit "pal" absolut nichts anfangen.

Die Docu zu dem Modul besagt:
For 2-D arrays, if pal is a valid (N,3) byte-array giving the RGB values (from 0 to 255) then mode='P',
Muss ich den datentyp des arrays extra festlegen, damit jedes Element dann auch wirklich 3byte lang ist oder wird das intern geregelt? Wenn ich es festlegen muss. Mache ich das über dtype? Wenn ja, kann mir jemand sagen, welchen dtype ich da wählen muss?


Vielleicht kann mir ja jemand helfen.

Danke.
Benutzeravatar
tromai
User
Beiträge: 92
Registriert: Mittwoch 26. April 2006, 11:20

Ok, ich habe Hilfe in der Mailinglist bekommen.
Pal ist im Prinzip die Farbpalette. Abgelegt wird sie als array. Deren Zeilen den Werten entspricht. Die Zahlenwerte des Arrays sind die RGB Werte.
Erzeugen kann man den Array z.B. so:

Code: Alles auswählen

map = numpy.empty((256,3),dtype=numpy.uint8)
map[:,1] = numpy.arange(0,256,dtype=numpy.uint8)
map[:,0] = map[:,1][::-1]
map[:,2] = map[:,0] + map[:,1]
Das wäre ein Colortable für die Werte 0-256.
Das Bildobjekt erzeuge ich dann folgendermaßen:

Code: Alles auswählen

i = scipy.misc.toimage(arr, high = 0, low = 255, pal=map, mode='P')
Antworten