Pixelwerte eines JPG Bildes 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
barisoezcan
User
Beiträge: 73
Registriert: Freitag 15. März 2013, 19:38

Hallo,

ich möchte mit den einzelnen Pixelwerten von einem JPG-Bild arbeiten.

Code: Alles auswählen

from PIL import Image

img = Image.open("Testbilder\Testbild.jpg")

pixels = img.getdata()

print(pixels[0])
Das Problem ist: Die Methode getdata() gibt pro Pixel 3 Werte zurück.
Die "einzelnen" Pixelwerte scheinen in RGB-Kanälen kodiert zu sein...
Gibt es keine Methode, die für einen Pixel nur je ein Wert liefert, die dieses Pixel vollständig repräsentiert?
Wenn nein, kann man diese 3 Werte pro Pixel in einen Wert umrechnen?
Wenn ja, wie genau?
BlackJack

@barisoezcan: Wie soll denn dieser *eine* Wert aussehen, der ein Pixel beschreibt?
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Man könnte die einzelnen Komponenten bitweise verschieben(R << 16, G << 8, B) und dann addieren, nur wofür braucht man das?
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
barisoezcan
User
Beiträge: 73
Registriert: Freitag 15. März 2013, 19:38

Weil ich eine vorgegebene Klasse habe, die ein beliebiges Bild mit einem vorgegebenen Bild pixelweise vergleicht.
Da dieses vorgegebene Bild für jedes Pixel nur einen Wert enthält, müsste dieses beliebige Bild auch dementsprechend übergeben werden.

Und noch ne andere Frage:

Wenn ich das hier ausführe:

Code: Alles auswählen

from PIL import Image

img = Image.open("Testbilder\schwarz.jpg")

pixels = img.load()

for i in range(50):
    for j in range(50):
        pixels[i, j] = (0, 0, 0)          #Alle Pixel auf schwarz setzen

for i in range(25,50):
    for j in range(25,50):
        pixels[i, j] = (255, 255, 255)         #Das untere rechte Viertel des Bildes auf weiss setzen

img.save("TestNeu.jpg")
Und dann mir die Pixelwerte des neuen Bildes "TestNeu.jpg" ausgeben lasse:

Code: Alles auswählen

for i in range(50):
    for j in range(50):
        print(pixels[i, j])
kommen unter anderem auch Werte ungleich 255 oder 0.
Woran könnte es liegen? An der verlustbehafteten Kompression von JPG?
Das wäre ein Ausschnitt der Ausgabe der Pixel-Werte:

(0, 0, 0)
(0, 0, 0)
(0, 0, 0)
(0, 0, 0)
(15, 15, 15)
(243, 243, 243)
(255, 255, 255)
(252, 252, 252)
(255, 255, 255)
(242, 242, 242)
BlackJack

@barisoezcan: Wenn Du das mit einem Referenzbild vergleichst und das nur einen Wert pro Pixel besitzt, dann musst Du doch irgendwie eine Vorstellung davon haben wie ein RGB-Wert, also drei Werte, auf einen Wert reduziert werden müssen, damit dieser Wert mit einem Wert aus dem Referenzbild vergleichbar ist. Man kann da ja nicht *irgendeine* Abbildung durchführen, oder?

Die Beobachtung bei den JPEG-Daten liegt an der Kompression. JPEG ist nicht dafür geeignet Daten zu speichern wo es tatsächlich auf die genauen Werte ankommt und nicht nur auf das ungefähre visuelle Erscheinungsbild. Da hilft übrigens auch kein drehen am Qualitätsparameter, denn alleine bei der diskreten Cosinus-Transformation können Rechenungenauigkeiten auftreten. Auch ein JPEG mit 100% Qualität muss nicht identisch mit dem Original sein.

Das PIL-Modul bietet übrigens noch mehr als `Image` — man hätte das Testbild nicht pixelweise mit Schleifen in Python erstellen müssen. Und sollte das Testbild auf der Platte 50×50 Pixel gross sein, macht es keinen Sinn das zu laden um die Daten im Speicher komplett zu ersetzen, man hätte auch einfach im Speicher ein Neues erstellen können.

Edit:

Code: Alles auswählen

#!/usr/bin/env python
from PIL import Image
from PIL.ImageDraw import Draw


def main():
    size = 50
    image = Image.new('RGB', (size, size))
    draw = Draw(image)
    draw.rectangle([size / 2, size / 2, size, size], fill='white')
    image.save('test.png')
    image.save('test.jpg')


if __name__ == '__main__':
    main()
Antworten