it-swarm.com.de

Liste der Pixelwerte von PIL abrufen

Leute, ich suche etwas Hilfe. Ich bin ein Neuling-Programmierer und eines der Probleme, die ich momentan habe, ist der Versuch, ein schwarzweißes .jpg-Bild in eine Liste zu konvertieren, die ich dann in ein Audiosignal modulieren kann. Dies ist Teil eines größeren Projekts zur Erstellung eines Python-SSTV-Programms.

Ich habe das PIL-Modul importiert und versuche die eingebaute Funktion aufzurufen: list(im.getdata()). Wenn ich es anrufe, stürzt Python ab. Gibt es eine Möglichkeit, das Bild (immer 320x240) in 240 Zeilen zu zerlegen, um die Berechnungen zu vereinfachen? Oder rufe ich nur die falsche Funktion an.

Wenn jemand Vorschläge hat, feuern Sie bitte ab. Wenn jemand Erfahrung mit der Erzeugung von modulierten Audiotönen mit Python hat, würde ich gerne "Perlen der Weisheit" akzeptieren, die sie bereit sind zu geben ... _. Vielen Dank im Voraus

25
Dave

Python sollte nicht abstürzen, wenn Sie getdata () aufrufen. Das Image ist möglicherweise beschädigt oder Ihre PIL-Installation ist fehlerhaft. Probieren Sie es mit einem anderen Bild aus oder veröffentlichen Sie das von Ihnen verwendete Bild.

Dies sollte das Bild wie gewünscht aufteilen:

from PIL import Image
im = Image.open('um_000000.png')

pixels = list(im.getdata())
width, height = im.size
pixels = [pixels[i * width:(i + 1) * width] for i in xrange(height)]
53
Nadia Alramli

Wenn Sie numpy installiert haben, können Sie Folgendes versuchen:

data = numpy.asarray(im)

(Ich sage hier "try", da es unklar ist, warum getdata() für Sie nicht funktioniert, und ich weiß nicht, ob asarray getdata verwendet, aber es ist einen Test wert.)

32
tom10

Ich gehe davon aus, dass Sie eine Fehlermeldung erhalten. TypeError: 'PixelAccess' object is not iterable...?

Informationen zum Zugriff auf Pixel finden Sie in der Dokumentation zu Image.load .

Um die Liste der Pixel in einem Bild zu erhalten, verwenden Sie PIL:

from PIL import Image
i = Image.open("myfile.png")

pixels = i.load() # this is not a list, nor is it list()'able
width, height = i.size

all_pixels = []
for x in range(width):
    for y in range(height):
        cpixel = pixels[x, y]
        all_pixels.append(cpixel)

Damit wird jedes Pixel an den all_pixels angehängt. Wenn es sich bei der Datei um ein RGB-Bild handelt (auch wenn es nur ein Schwarzweißbild enthält), handelt es sich hier um ein Tuple-Beispiel:

(255, 255, 255)

Um das Bild in Monochrom zu konvertieren, mitteln Sie einfach die drei Werte - so werden die letzten drei Codezeilen.

cpixel = pixels[x, y]
bw_value = int(round(sum(cpixel) / float(len(cpixel))))
# the above could probably be bw_value = sum(cpixel)/len(cpixel)
all_pixels.append(bw_value)

Oder um die Leuchtdichte (gewichteter Durchschnitt) zu erhalten:

cpixel = pixels[x, y]
luma = (0.3 * cpixel[0]) + (0.59 * cpixel[1]) + (0.11 * cpixel[2])
all_pixels.append(luma)

Oder reines 1-Bit-Schwarzweißbild:

cpixel = pixels[x, y]
if round(sum(cpixel)) / float(len(cpixel)) > 127:
    all_pixels.append(255)
else:
    all_pixels.append(0)

Es gibt wahrscheinlich Methoden in PIL, um solche RGB -> BW-Konvertierungen schneller durchzuführen, aber dies funktioniert und ist nicht besonders langsam.

Wenn Sie nur Berechnungen für jede Zeile durchführen möchten, können Sie das Hinzufügen aller Pixel zu einer Zwischenliste überspringen. So können Sie beispielsweise den Durchschnittswert jeder Zeile berechnen:

from PIL import Image
i = Image.open("myfile.png")

pixels = i.load() # this is not a list
width, height = i.size
row_averages = []
for y in range(height):
    cur_row_ttl = 0
    for x in range(width):
        cur_pixel = pixels[x, y]
        cur_pixel_mono = sum(cur_pixel) / len(cur_pixel)
        cur_row_ttl += cur_pixel_mono

    cur_row_avg = cur_row_ttl / width
    row_averages.append(cur_row_avg)

print "Brighest row:",
print max(row_averages)
13
dbr

Oder wenn Sie weiße oder schwarze Pixel zählen möchten

Dies ist auch eine Lösung:

from PIL import Image
import operator

img = Image.open("your_file.png").convert('1')
black, white = img.getcolors()

print black[0]
print white[0]
3

Nicht PIL, aber scipy.misc.imread könnte trotzdem interessant sein:

import scipy.misc
im = scipy.misc.imread('um_000000.png', flatten=False, mode='RGB')
print(im.shape)

gibt

(480, 640, 3)

so ist es (Höhe, Breite, Kanäle). So können Sie darüber iterieren

for y in range(im.shape[0]):
    for x in range(im.shape[1]):
        color = Tuple(im[y][x])
        r, g, b = color
1
Martin Thoma

Wie ich oben kommentiert habe, scheint das Problem die Konvertierung vom internen PIL-Listenformat in einen Standard-Python-Listentyp zu sein. Ich habe festgestellt, dass Image.tostring () viel schneller ist und je nach Bedarf ausreichend ist. In meinem Fall musste ich den CRC32-Digest der Bilddaten berechnen, und er passte gut dazu.

Wenn Sie komplexere Berechnungen durchführen müssen, kann es sein, dass Sie eine Tom10-Antwort mit numpy benötigen.

1
jesjimher
data = numpy.asarray(im)

Hinweis : In PIL ist img RGBA. In cv2 ist img BGRA.

Meine robuste Lösung:

def cv_from_pil_img(pil_img):
    assert pil_img.mode=="RGBA"
    return cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGBA2BGRA)
0
sunshine
pixVals = list(pilImg.getdata())

ausgabe ist eine Liste aller RGB-Werte aus dem Bild:

[(248, 246, 247), (246, 248, 247), (244, 248, 247), (244, 248, 247), (246, 248, 247), (248, 246, 247), (250, 246, 247), (251, 245, 247), (253, 244, 247), (254, 243, 247)]
0
Linda

Sieht aus, als hätte PILlow tostring() in tobytes() geändert. Beim Versuch, RGBA-Pixel zu extrahieren, um sie in eine OpenGL-Textur zu bringen, funktionierten die folgenden für mich (innerhalb des glTexImage2D-Aufrufs, den ich der Kürze halber weglasse).

from PIL import Image
img = Image.open("mandrill.png").rotate(180).transpose(Image.FLIP_LEFT_RIGHT)

# use img.convert("RGBA").tobytes() as texels
0
Dr. D.