Wie bekomme ich ein Bild von 100 Bildern mit PIL?

Zum Beispiel habe ich 100 Bilder, deren Auflösung gleich ist, und ich möchte sie in ein Bild verschmelzen. Für das endgültige Bild ist der RGB-Wert jedes Pixels der Durchschnitt der 100 Bilder an dieser Stelle. Ich weiß, dass die getdata Funktion in dieser Situation arbeiten kann, aber gibt es einen einfacheren und schnelleren Weg, dies in PIL (Python Image Library) zu tun?

5 Solutions collect form web for “Wie bekomme ich ein Bild von 100 Bildern mit PIL?”

Nehmen wir an, dass Ihre Bilder alle .png-Dateien sind und sie alle im aktuellen Arbeitsverzeichnis gespeichert sind. Der Python-Code unten wird tun, was Sie wollen. Wie Ignacio vorschlägt, ist die Verwendung von numpy zusammen mit PIL der Schlüssel hier. Sie müssen nur ein bisschen vorsichtig sein, um zwischen Integer und Float Arrays zu wechseln, wenn Sie Ihre durchschnittlichen Pixelintensitäten aufbauen.

 import os, numpy, PIL from PIL import Image # Access all PNG files in directory allfiles=os.listdir(os.getcwd()) imlist=[filename for filename in allfiles if filename[-4:] in [".png",".PNG"]] # Assuming all images are the same size, get dimensions of first image w,h=Image.open(imlist[0]).size N=len(imlist) # Create a numpy array of floats to store the average (assume RGB images) arr=numpy.zeros((h,w,3),numpy.float) # Build up average pixel intensities, casting each image as an array of floats for im in imlist: imarr=numpy.array(Image.open(im),dtype=numpy.float) arr=arr+imarr/N # Round values in array and cast as 8-bit integer arr=numpy.array(numpy.round(arr),dtype=numpy.uint8) # Generate, save and preview final image out=Image.fromarray(arr,mode="RGB") out.save("Average.png") out.show() 

Das Bild unten wurde aus einer Folge von HD-Videorahmen mit dem obigen Code erzeugt.

Durchschnitt von HD-Videorahmen

Ich finde es schwierig, sich eine Situation vorzustellen, in der Gedächtnis hier ein Problem ist, aber in dem (unwahrscheinlichen) Ereignis, das Sie sich absolut nicht leisten können, das Array von Floats zu erstellen, die für meine ursprüngliche Antwort erforderlich sind, könnten Sie PILs Blendfunktion verwenden, wie von @ MHurley wie folgt:

 # Alternative method using PIL blend function avg=Image.open(imlist[0]) for i in xrange(1,N): img=Image.open(imlist[i]) avg=Image.blend(avg,img,1.0/float(i+1)) avg.save("Blend.png") avg.show() 

Sie können die korrekte Reihenfolge der Alpha-Werte ableiten, beginnend mit der Definition aus der PIL-Mischfunktion:

 out = image1 * (1.0 - alpha) + image2 * alpha 

Denken Sie daran, diese Funktion rekursiv auf einen Vektor von Zahlen (anstatt Bilder) anzuwenden, um den Mittelwert des Vektors zu erhalten. Für einen Vektor der Länge N benötigen Sie N-1 Mischoperationen mit N-1 verschiedenen Werten von Alpha.

Allerdings ist es wahrscheinlich leichter, intuitiv über die Operationen nachzudenken. Bei jedem Schritt soll das avg-Bild gleiche Verhältnisse der Quellbilder aus früheren Schritten enthalten. Beim Mischen der ersten und zweiten Quellbilder sollte Alpha 1/2 sein, um gleiche Proportionen zu gewährleisten. Wenn man das dritte mit dem Durchschnitt der ersten beiden mischt, möchte man das neue Bild aus 1/3 des dritten Bildes zusammensetzen, wobei der Rest aus dem Durchschnitt der vorherigen Bilder besteht (aktueller Wert von avg) , und so weiter.

Grundsätzlich sollte diese neue Antwort, die auf dem Mischen basiert, in Ordnung sein. Allerdings weiß ich nicht genau, wie die Blend-Funktion funktioniert. Das macht mir keine Sorgen darüber, wie die Pixelwerte nach jeder Iteration abgerundet werden.

Das Bild unten wurde aus 288 Quellbildern mit dem Code aus meiner ursprünglichen Antwort generiert:

Durchschnittliche, ursprüngliche Antwort

Auf der anderen Seite wurde dieses Bild durch wiederholtes Anwenden der PIL-Mischfunktion auf dieselben 288 Bilder erzeugt:

Blended, mit Image.blend

Ich hoffe, dass Sie sehen können, dass die Ausgänge der beiden Algorithmen merklich anders sind. Ich erwarte, dass dies wegen der Akkumulation von kleinen Rundungsfehlern während der wiederholten Anwendung von Image.blend ist

Ich empfehle meine ursprüngliche Antwort über diese Alternative.

Ich würde erwägen, ein Array von x durch y ganze Zahlen zu erstellen, die alle ab (0, 0, 0) beginnen und dann für jedes Pixel in jeder Datei den RGB-Wert einfügen, alle Werte mit 100 teilen und dann das Bild von diesem erstellen – du Wird wahrscheinlich feststellen, dass numpy kann helfen.

Man kann auch numpy Mittelfunktion für die Mittelung verwenden. Der Code sieht besser aus und arbeitet schneller.

Hier ist der Vergleich von Timing und Ergebnissen für 700 laute Graustufen Bilder von Gesichtern:

 def average_img_1(imlist): # Assuming all images are the same size, get dimensions of first image w,h=Image.open(imlist[0]).size N=len(imlist) # Create a numpy array of floats to store the average (assume RGB images) arr=np.zeros((h,w),np.float) # Build up average pixel intensities, casting each image as an array of floats for im in imlist: imarr=np.array(Image.open(im),dtype=np.float) arr=arr+imarr/N out = Image.fromarray(arr) return out def average_img_2(imlist): # Alternative method using PIL blend function N = len(imlist) avg=Image.open(imlist[0]) for i in xrange(1,N): img=Image.open(imlist[i]) avg=Image.blend(avg,img,1.0/float(i+1)) return avg def average_img_3(imlist): # Alternative method using numpy mean function images = np.array([np.array(Image.open(fname)) for fname in imlist]) arr = np.array(np.mean(images, axis=(0)), dtype=np.uint8) out = Image.fromarray(arr) return out average_img_1() 100 loops, best of 3: 362 ms per loop average_img_2() 100 loops, best of 3: 340 ms per loop average_img_3() 100 loops, best of 3: 311 ms per loop 

BTW, die Ergebnisse der Mittelung sind ganz anders. Ich denke, die erste Methode verliert Informationen während der Mittelung. Und der zweite hat einige Artefakte.

Average_img_1

Bildbeschreibung hier eingeben

Average_img_2

Bildbeschreibung hier eingeben

Average_img_3

Bildbeschreibung hier eingeben

Ich lief in MemoryErrors, wenn ich die Methode in der akzeptierten Antwort versuche. Ich fand einen Weg zu optimieren, das scheint das gleiche Ergebnis zu produzieren. Grundsätzlich vermischen Sie ein Bild zu einer Zeit, anstatt sie alle hinzuzufügen und zu teilen.

 N=len(images_to_blend) avg = Image.open(images_to_blend[0]) for im in images_to_blend: #assuming your list is filenames, not images img = Image.open(im) avg = Image.blend(avg, img, 1/N) avg.save(blah) 

Das tut zwei Sachen, du musst nicht zwei sehr dichte Kopien des Bildes haben, während du das Bild in ein Array drehst, und du musst überhaupt keine 64-Bit-Schwimmer verwenden. Sie erhalten ähnlich hohe Präzision, mit kleineren Zahlen. Die Ergebnisse ERHÖHEN, um das gleiche zu sein, obwohl ich würde schätzen, wenn jemand meine Mathematik überprüft.

  • Python Hinzufügen zusätzlicher Fläche zum Bild
  • Spark mit PySpark Bilder lesen
  • Ndimage- oder Skimage-Funktionen für die Rückgabe von Pixel-Nachbarschaften
  • Speichern von Bildern im Datenspeicher von GAE python bei der Bereitstellung von web2py app
  • Wie konvertiere ich ein numpy Array zu (und Display) ein Bild?
  • PIL image.open () arbeitet für einige Bilder aber nicht andere
  • Image Upload in Google App Engine
  • Erkennung von Bildern in Python
  • Python Matplotlib Basemap Overlay kleines Bild auf Kartenplot
  • Wie bekomme ich python, um große Bilder aus dem Internet erfolgreich herunterzuladen
  • Wie konvertiert man Graustufenwerte in Matrix zu einem Bild in Python?
  • Python ist die beste Programmiersprache der Welt.