PIL RGB-Farbwert auslesen

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
Birne94
User
Beiträge: 90
Registriert: Freitag 28. November 2008, 15:18
Kontaktdaten:

HI^^
Wie kann ich mit PIL den Farbwert eines Pixels auslesen?
Mit getpixel kommt ich nicht weiter :-(
BlackJack

@Birne94: Das geht mit `getpixel()` auf dem `Image`-Exemplar. Was heisst also Du kommst damit nicht weiter genau!?
OverNord
User
Beiträge: 72
Registriert: Donnerstag 24. Januar 2008, 11:59
Kontaktdaten:

Birne94 hat geschrieben: Wie kann ich mit PIL den Farbwert eines Pixels auslesen?
Mit getpixel kommt ich nicht weiter :-(

Code: Alles auswählen

import Image
img = Image.open('bild.png')
img.getpixel((17, 42))
So schwer ist das doch nicht.
Birne94
User
Beiträge: 90
Registriert: Freitag 28. November 2008, 15:18
Kontaktdaten:

ja. und dann erhalte ich eine Zahl, zB 19.
Wie kann ich das dann in den RGB wert umwandeln...?
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Es könnte sein, dass das Bild eine Farbpalette benutzt (`img.mode` müsste dann "P" sein), dann gibt `getpixel()` eben den Index zurück. An die RGB-Farbe kommst du dann mit `getpalette()` oder du konvertierst das Bild einfach vorher schon in ein RGB-Bild.

Beispiel:

Code: Alles auswählen

assert img.mode == 'P'

index = img.getpixel((1,1))
r, g, b = img.getpalette()[index * 3:index * 3 + 3]

# oder eben
r, g, b = img.convert('RGB').getpixel((1,1))
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
raimund
User
Beiträge: 9
Registriert: Mittwoch 30. September 2009, 10:11

Hallo zusammen,

dies ist mein erster Beitrag in eurem Forum. Kurz was zu mir. Ich bin was Python angeht totaler Laie und beschäftige mich seit heute morgen mit der Materie. Für meine Doktorarbeit muss ich allerdings einige Berechnungen anstellen, so dass ich mich entschieden habe, mich in Python einzuarbeiten. Dabei hat mir folgende Seite die ersten Schritte deutlich erleichtert:

http://www.wspiegel.de/pykurs/kurs_index.htm

Für euch ist das wahrscheinlich schon lange kein Thema mehr, aber man muss ja mal anfangen... :roll:

Nun zu meinem konkreten Anliegen:
Ich möchte gerne aus jpg-Bildern RGB-Information herausziehen. Der erste Schritt ist mir soeben gelungen. Ich habe mit der PIL und getpixel RGB-Daten von einem bestimmten Pixel bekommen. Super, das war mein erstes Erfolgserlebnis! :D

Code: Alles auswählen

from PIL import Image
import Image
im = Image.open('c:/test.jpg')
im.getpixel((x,y))
Weiter im Text: Der nächste Schritt wäre für mich, dass ich von einer bestimmten Region im Bild einen Mittelwert von den Rot- Grün- und Blau-Informationen bekomme. Konkret: ein Foto ist 500x500 pixel groß. Ich brauche von der Fläche x1=200, x2=300, y1=200 und y2=300 einen mittleren Rot, Grün und Blau-Wert. Die Standardabweichung davon könnte ich vielleicht dann selber errechen. Das wird ja dann sehr ähnlich wie die Mittelwertberechnung sein.

Habe mir schon Gedanken dazu gemacht, aber leider stecke ich noch nicht so sehr in der Programmier-Sprache drin. Die Zeit mich nun Wochen einzuarbeiten habe ich leider auch nicht. Vielleicht kennt sich ja einer von euch besser damit aus.

Würde mich über Hilfe sehr freuen!
Viele Grüße,
raimund.
raimund
User
Beiträge: 9
Registriert: Mittwoch 30. September 2009, 10:11

so... nach der Mittagspause der nächste Erfolg. Ich habe es schon mal geschafft, die RGB-Daten zu trennen. In einem anderen Forum habe ich ein Skript dafür gefunden.

Danke an TheSplit aus dem gulli:board!
(Vorausgesetzt wird Python und die Installation von PIL. Das kleine Programm liest den Ordner "Images" aus und speichert jeden Bildkanal in Farbabstufungen und in Helligkeitsstufen in den Ordner "img_channels")

Code: Alles auswählen

import Image, ImageOps

from os import listdir
from string import rfind

imgfolder = 'Images'
channelfolder = 'img_channels'

channels = ['R', 'G', 'B']

for image in listdir(imgfolder):
    Imgfile = Image.open(imgfolder+'\\'+image)
    img_channels = Imgfile.split()
    
    c = 0
    img_name = image[:rfind(image, '.')]
    img_type = image[rfind(image, '.') +1:]
    for channel in img_channels:
        ch_name = channels[c]
        if ch_name == 'R':
            color = (255,0,0)
        elif ch_name == 'G':
            color = (0,255,0)
        elif ch_name == 'B':
            color = (0,0,255)
        ImageOps.colorize(channel, (0,0,0),color).save(channelfolder+'\\'+img_name+ch_name+'_color.'+img_type, 'JPEG')
        channel.save(channelfolder+'\\'+img_name+ch_name+'_grey.'+img_type, 'JPEG')
        c += 1
so komme ich vielleicht besser voran...
Zum Schluss sollte eh ein Skript rauskommen, dass einen ganzen Haufen Bilder automatisch verarbeitet. Daher ist das Skript von TheSplit schon mal eine große Hilfe.

Jetzt muss ich nur noch diese Mittelwerte berechnen... mmmmh....
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Der Code von Trundle liefert dir wesentlich direkter die einzelnen Farbwerte (er hat sie r, g, b genannt, warum wohl?) zurück.
raimund
User
Beiträge: 9
Registriert: Mittwoch 30. September 2009, 10:11

ja, das ist klar. Aber ich muss die RGB-Werte ja von vielen verschiedenen Pixeln berechnen. Ich dachte, da wäre es vielleicht praktischer, erstmal die Kanäle zu trennen...

so oder so... weiß halt nicht wie ich statt "im.getpixel((x,y))" eine range von mehreren Pixeln angeben kann. Vielleicht bin ich auch total auf dem Holzweg! Mal schauen...
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Auch in den einzelnen Farbkanälen müsstest du die einzelnen Werte pro Wert betrachten, oder? Eventuell könnte natürlich hier numpyeffektiver eingesetzt werden. In numpy sollte sowas wie Matrizenberechnung, Standardabweichung etc. eigentlich kein Problem sein.
raimund
User
Beiträge: 9
Registriert: Mittwoch 30. September 2009, 10:11

danke, mkallas, aber ich glaube ich bin soeben fündig geworden:

mühsam ernährt sich das Eichhörnchen...

Habe was gefunden: The ImageStat Module
http://effbot.org/imagingbook/imagestat.htm

Code: Alles auswählen

import Image
import ImageStat
im = Image.open('test.jpg')
stat = ImageStat.Stat(im)
print stat.mean
Gibt mir zumindest schon mal einen Mittelwert des gesamten Bildes aus. Nun muss ich noch eine Maske definieren...
raimund
User
Beiträge: 9
Registriert: Mittwoch 30. September 2009, 10:11

so... ich lasse euch ja nicht dumm sterben:
hier was zur Maske.

Code: Alles auswählen

import Image
import ImageStat
im = Image.open('c:/test.jpg')
mask = Image.open('c:/test_mask.bmp')
# Maske muss gleiche Größe wie das Originalbild haben und im Modus 1 oder L abgespeichert sein
# alle Pixel, die in der Maske ungleich null sind, werden dabei im Original ausgewertet
stat = ImageStat.Stat(im,mask)
# ohne Verwendung der Maske: "stat = ImageStat.Stat(im)"
print stat.mean
nun muss ich die Skripte noch irgendwie aneinanderhängen...
BlackJack

@raimund: Ich dachte der Bereich ist rechteckig!? Dann ist eine Maske vielleicht overkill. Du könntest doch einfach mit der `crop()`-Methode den überflüssigen Teil der Daten vorher entsorgen.
raimund
User
Beiträge: 9
Registriert: Mittwoch 30. September 2009, 10:11

wahrscheinlich wird er rechteckig, vielleicht aber auch nicht. kannst Du mir ein kurzes Beispiel posten, wie das mit dem crop geht. Danke!
BlackJack

So kompliziert ist die Methode ja nicht. Was für Fragen lässt die Dokumentation denn offen?

http://effbot.org/imagingbook/image.htm ... Image.crop
raimund
User
Beiträge: 9
Registriert: Mittwoch 30. September 2009, 10:11

ok, habs geschnallt. Danke nochmal für den Tipp!

btw: schöne Grüße an den User "Doik" von TheSplit!
BlackJack

@raimund: Wobei das Skript aus dem Gulli-Board nicht besonders gut ist.

Aus dem `string`-Modul sollte man keine Funktionen mehr verwenden, die es auch als Methoden auf Zeichenketten gibt.

`channels` zusammen mit der ``if``/``elif``-Kaskade ist unnötig indirekt und kompliziert.

Zum ermitteln von `img_name` und `img_typ` gibt es `os.path.splitext()`. Zum plattformunabhängigen zusammensetzen von Pfaden ist `os.path.join()` da.

`c` ist überfüssig, wenn man mittels `zip()` oder `itertools.izip()` über `channels` und `img_channels` gleichzeitig iteriert.
raimund
User
Beiträge: 9
Registriert: Mittwoch 30. September 2009, 10:11

danke für den Hinweis, aber da ich mich erst seit wenigen Stunden mit Python geschäftige, müsstest Du ungefähr wissen, dass ich erstmal zufrieden bin, dass es funzt. Deine Änderungen würden mich vielleicht Tage oder Wochen kosten, damit es irgendwie anders funktioniert. Im Ergebnis wirds wohl keinen Unterschied machen.

Ich hoffe Du verstehst was ich meine...
BlackJack

@raimund: Ich verstehe schon. Leute die nur irgendwie ein Problem gelöst bekommen wollen, und denen egal ist, wie die Lösung aussieht. Amateure. Ganz furchtbar. ;-) :-D
raimund
User
Beiträge: 9
Registriert: Mittwoch 30. September 2009, 10:11

leider kann ich mich nicht in jedes Themengebiet 100%ig einarbeiten. Das ist schade. Aber zumindest habe ich heute nichts anderes gemacht, als im Internet zu suchen und zu probieren und bin eigentlich schon recht weit gekommen. Ohne Hilfe würde es halt Wochen dauern. Bin ja keiner, der hier nur ein Posting absetzt und auf n fertiges Skript wartet. Ich hoffe, den Eindruck habe ich nicht erzeugt.

Morgen früh in der Uni gehts sofort weiter... Danke!
Antworten