PIL / Pillow ist eine kompakte und schnelle Bildbibliothek für Python. Wir haben häufig verwendete Prozesse zusammengefasst (von Zeit zu Zeit aktualisiert).
Grundsätzlich gibt es keinen Grund, PIL zu verwenden. Pillow hat eine Fehlerbehebung für den Größenänderungsfilter und ist von höherer Qualität.
Pillow ist sehr schnell abgestimmt und läuft immer schneller als eine ähnliche Bibliothek, ImageMagick. "Getpixel" / "Putpixel" ist jedoch sehr langsam. Verwenden Sie es daher nur für die Bilderzeugung. Es gibt auch eine schnellere "Pillow-Simd". Es scheint ungefähr 4 bis 5 Mal schneller zu sein als das Originalkissen.
pillow-simd https://github.com/uploadcare/pillow-simd
https://python-pillow.org/pillow-perf/
Modus | Erläuterung |
---|---|
1 | Bei Verwendung für eine 1-Bit-Maske ist eine logische Berechnung möglich |
L | 8bit Graustufen |
P | Palettenmodus |
RGB | 8bit x 3 |
RGBA | 8bit x 4 Transparenz(Alpha)Mit |
CMYK | 8bit x 4 Wird häufig zum Drucken verwendet |
YCbCr | Wird häufig für 8-Bit x 3-Videos verwendet |
HSV | Nur 8bit x 3 Kissen |
RGBa | RGB-Wert mit Alphakanal multiplizieren |
LA | Multiplizieren Sie den L-Wert mit dem Alpha-Kanal |
I | 32-Bit-Ganzzahl |
F | 32bit schwimmende Minderheit |
Filter | Downscaling-Qualität | Upscaling-Qualität | Performance |
---|---|---|---|
Image.NEAREST | ⭐⭐⭐⭐⭐ | ||
Image.BOX | ⭐ | ⭐⭐⭐⭐ | |
Image.BILINEAR | ⭐ | ⭐ | ⭐⭐⭐ |
Image.HAMMING | ⭐⭐ | ⭐⭐⭐ | |
Image.BICUBIC | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
Image.LANCZOS | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐ |
img.convert("L")
alpha.convert("LA")
→
Übrigens berücksichtigt convert ('L')
den Alpha-Wert nicht.
alpha.convert("L")
→
img.convert("HSV")
Nur Kissen können in HSV-Farbraum umgewandelt werden. Es besteht aus drei Komponenten: Farbton, Sättigung und Wert. Das Folgende ist ein Beispiel für das Verschieben des Farbrads.
h, s, v = img.convert("HSV").split()
_h = ImageMath.eval("(h + 128) % 255", h=h).convert("L")
Image.merge("HSV", (_h, s, v)).convert("RGB")
CIE XYZ ist ein Farbraum, der so angepasst ist, dass der euklidische Abstand zwischen den Farben dem vom Menschen wahrgenommenen Unterschied entspricht.
rgb2xyz = (
0.412453, 0.357580, 0.180423, 0,
0.212671, 0.715160, 0.072169, 0,
0.019334, 0.119193, 0.950227, 0
)
img.convert("RGB", rgb2xyz)
gray = img.convert("L") #In Graustufen konvertieren
gray.point(lambda x: 0 if x < 230 else x) #Wenn der Wert 230 oder weniger beträgt, ist er 0.
img.point(lambda x: x * 1.5) # 1.Mach es 5 mal heller
img.point(lambda x: x * 0.5) # 1 /Verdunkeln Sie auf 2
Konvertieren Sie das Bild in Graustufen und dann in Sepia.
gray = img.convert("L")
Image.merge(
"RGB",
(
gray.point(lambda x: x * 240 / 255),
gray.point(lambda x: x * 200 / 255),
gray.point(lambda x: x * 145 / 255)
)
)
Die Gammakorrektur kann auch mithilfe einer Nachschlagetabelle mit sehr hoher Geschwindigkeit konvertiert werden. Unter der Annahme, dass src = Eingabefarbe, γ = Gammawert und g = Verstärkungswert ist, lautet die Gammakorrekturformel wie folgt.
dst = \biggl(\frac{src}{255}\biggr)^{1/γ} \times g \times 255
def gamma_table(gamma_r, gamma_g, gamma_b, gain_r=1.0, gain_g=1.0, gain_b=1.0):
r_tbl = [min(255, int((x / 255.) ** (1. / gamma_r) * gain_r * 255.)) for x in range(256)]
g_tbl = [min(255, int((x / 255.) ** (1. / gamma_g) * gain_g * 255.)) for x in range(256)]
b_tbl = [min(255, int((x / 255.) ** (1. / gamma_b) * gain_b * 255.)) for x in range(256)]
return r_tbl + g_tbl + b_tbl
img.point(gamma_table(1.2, 0.5, 0.5))
Es ist besser, "Lambda" nicht in der Schleife an "Image.point" zu übergeben. Es ist schneller, es im Voraus zu erweitern, da das an "Point" übergebene Argument nur eine Konvertierungstabelle ist.
for ...:
img.point(lambda x: x * 100)
#Der untere Prozess ist gleich dem oberen Prozess, aber schneller
table = [x * 100 for x in range(256)] * len(img.getbands())
for ...:
img.point(table)
getbbox
Image.getbbox
gibt den kleinsten Wert ungleich Null im Bild zurück, ein Bild mit allen 0-Werten gibt None
zurück.
alpha = Image.open("alpha.png ")
crop = alpha.split()[-1].getbbox()
alpha.crop(crop)
→
Wenn die beiden Bilder gleich sind, gibt "ImageChops.difference" alle 0 Bilder zurück. Wenn "getbbox" "None" ist, kann dies als gleich beurteilt werden.
ImageChops.difference(img1, img2).getbbox() is None
img.resize((128, 128), Image.LANCZOS)
Im Gegensatz zur Größenänderung behalten Miniaturansichten ihr Seitenverhältnis bei. Beachten Sie, dass "Thumbnail" aus irgendeinem Grund eine destruktive Methode ist, sondern "Image.copy". Es ist daher eine gute Idee, ein Duplikat zu erstellen.
img.thumbnail((128, 128), Image.LANCZOS)
img.size
# (128, 79)
Wenn Sie für das Argument "Erweitern" "Wahr" angeben, wird das Bild erweitert, wenn es beim Drehen wächst.
img.rotate(90, expand=True)
Die Mosaikverarbeitung kann mit "Image.LINEAR" verkleinert und vergrößert werden. Wenn Sie sie jedoch nach dem Anwenden der Gaußschen Unschärfe verkleinern, handelt es sich um ein weiches Mosaik.
#Gezacktes Mosaik
img.resize([x // 8 for x in img.size]).resize(img.size)
#Wenden Sie Gaußsche Unschärfe für ein weiches Mosaik an
gimg = img.filter(ImageFilter.GaussianBlur(4))
gimg.resize([x // 8 for x in img.size]).resize(img.size)
Image.blend(img,effect_img, 0.5)
img.quantize(4) #Reduziert auf 4 Farben
Um ein Bild mit Alpha einzufügen, geben Sie das Bild mit Alpha im Argument "Maske" von "Image.paste" an.
img.paste(alpha, mask=alpha)
Image.getcolors
, das die verwendeten Farben zählt, kann ohne Argument nicht mehr als 255 Farben zählen.
Bei Bildern, die mehr als 255 Farben verwenden, ist es sicher, die Anzahl der Pixel als Argument zu übergeben. [^ 1]
[^ 1]: 2017-02-07 Behoben Es war 'Image.getcount', aber es ist korrekt 'Image.getcolors', ich werde es reparieren.
img.getcolors(img.size[0] * img.size[1])
Gibt eine Liste von Bildfarbhistogrammen zurück. Da jedes Band kontinuierlich zurückgegeben wird, werden im RGB-Modus 256 x 3 = 768 Elemente zurückgegeben.
img.histogram()
Es gibt keine Methode zum Ersetzen von Farben. Wenn Sie Farben ersetzen möchten, lesen Sie bitte den folgenden Artikel.
Ersetzen Sie Bildfarben schnell durch PIL / Kissen
ImageOps.invert(img)
ImageOps.mirror(img) #Horizontal spiegeln
ImageOps.flip(img) #auf den Kopf stellen
Färbt ein Graustufenbild mit einem Pixelwert von 0 bis "Schwarz" und einem Pixelwert von 255 bis "Weiß".
gray = ImageOps.grayscale(img)
ImageOps.colorize(gray, black=(0, 0, 0), white=(255, 255, 0))
→
Reduziert die Bittiefe des Bildes auf den Wert des Arguments, um die Farbe zu vereinfachen.
ImageOps.posterize(img, 2)
Invertiert alle Pixelwerte über dem Schwellenwert. Ich weiß nicht, wo ich es verwenden soll.
ImageOps.solarize(img, 128)
Gleichen Sie das Bildhistogramm aus. Wenden Sie eine nichtlineare Zuordnung auf das Eingabebild an, um eine gleichmäßige Verteilung der Graustufenwerte im Ausgabebild zu erstellen.
ImageOps.equalize(img)
Das ImageChops-Modul ist ein Modul, das Kanäle bearbeitet.
Das Bild links ist das betroffene Bild, und das Bild rechts ist das Bild für den Effekt. In diesem Kapitel werden diese beiden Bilder als Beispiele verwendet.
ImageChops.add(img, effect_img) # img + effect_img
ImageChops.subtract(img, effect_img) # img - effect_img
ImageChops.add_modulo(img, effect_img) # img + effect_img % MAX
ImageChops.subtract_modulo(img, effect_img) # img - effect_img % MAX
ImageChops.multiply(img, effect_img)
ImageChops.screen(img, effect_img)
ImageChops.lighter(img, effect_img)
ImageChops.darker(img, effect_img)
ImageChops.difference(img, effect_img)
ImageChops.offset(img, 100, 100)
Führt eine Faltung durch (Faltungsberechnung). Verschiedene Bildkonvertierungen werden durchgeführt, indem die als Kernel bezeichnete Matrix neu angeordnet wird.
Parameter | Erläuterung |
---|---|
size | Kernelgröße |
scale | Teilen Sie nach der Matrixoperation durch diesen Wert |
offset | Addiere diesen Wert nach der Matrixoperation |
kernel | Faltungsmatrix |
https://github.com/python-pillow/Pillow/blob/6e7553fb0f12025306b2819b9b842adf6b598b2e/PIL/ImageFilter.py
ImageFilter.BLUR
img.filter(ImageFilter.BLUR)
# size: (5, 5),
# scale: 16,
# offset: 0,
# kernel:(
# 1, 1, 1, 1, 1,
# 1, 0, 0, 0, 1,
# 1, 0, 0, 0, 1,
# 1, 0, 0, 0, 1,
# 1, 1, 1, 1, 1
# )
ImageFilter.DETAIL
img.filter(ImageFilter.DETAIL)
# size: (3, 3),
# scale: 6,
# offset: 0,
# kernel: (
# 0, -1, 0,
# -1, 10, -1,
# 0, -1, 0
# )
ImageFilter.SHAPEN
img.filter(ImageFilter.SHARPEN)
# size: (3, 3),
# scale: 16,
# offset: 0,
# kernel: (
# -2, -2, -2,
# -2, 32, -2,
# -2, -2, -2
# )
ImageFilter.CONTOUR
img.filter(ImageFilter.CONTOUR)
# size: (3, 3),
# scale: 1,
# offset: 255,
# kernel: (
# -1, -1, -1,
# -1, 8, -1,
# -1, -1, -1
# )
ImageFilter.EDGE_ENHANCE / ImageFilter.EDGE_ENHANCE_MORE
img.filter(ImageFilter.EDGE_ENHANCE)
# size: (3, 3),
# scale: 2,
# offset: 0,
# kernel: (
# -1, -1, -1,
# -1, 10, -1,
# -1, -1, -1
# )
img.filter(ImageFilter.EDGE_ENHANCE_MORE)
# size: (3, 3),
# scale: 1,
# offset: 0,
# kernel: (
# -1, -1, -1,
# -1, 9, -1,
# -1, -1, -1
# )
ImageFilter.EMBOSS
img.filter(ImageFilter.EMBOSS)
# size: (3, 3),
# scale: 1,
# offset: 128,
# kernel: (
# -1, 0, 0,
# 0, 1, 0,
# 0, 0, 0
# )
ImageFilter.FIND_EDGES
img.filter(ImageFilter.FIND_EDGES)
# size: (3, 3),
# scale: 1,
# offset: 0,
# kernel: (
# -1, -1, -1,
# -1, 8, -1,
# -1, -1, -1
# )
ImageFilter.SMOOTH / ImageFilter.SMOOTH_MORE
img.filter(ImageFilter.SMOOTH)
# size: (3, 3),
# scale: 13,
# offset: 0,
# kernel: (
# 1, 1, 1,
# 1, 5, 1,
# 1, 1, 1
# )
#
img.filter(ImageFilter.SMOOTH_MORE)
# size: (5, 5),
# scale: 100,
# offset: 0,
# kernel: (
# 1, 1, 1, 1, 1,
# 1, 5, 5, 5, 1,
# 1, 5, 44, 5, 1,
# 1, 5, 5, 5, 1,
# 1, 1, 1, 1, 1
# )
Gaußsche Unschärfeにより画面の平滑化します。
img.filter(ImageFilter.GaussianBlur(1.0))
img.filter(ImageFilter.GaussianBlur(1.5))
img.filter(ImageFilter.GaussianBlur(3.0))
"MaxFilter" heißt Dilatation und "MinFilter" heißt Erosion.
img.filter(ImageFilter.MinFilter())
img.filter(ImageFilter.MaxFilter())
Expansion / Kontraktion / Öffnen / Schließen
MedianFilter
wird häufig verwendet, um Rauschen zu entfernen, und seine Konturen sind weniger unscharf als bei Gauß-Filtern.
img.filter(ImageFilter.MedianFilter())
→
Wählt den am häufigsten verwendeten Pixelwert in einem Feld der angegebenen Größe aus. Pixelwerte, die nur ein- oder zweimal auftreten, werden ignoriert. ~~ Ich weiß nicht, wo ich es verwenden soll. Siehe ~~ Fotos mit Pillow's Mode Filter wie Gemälde aussehen lassen.
img.filter(ImageFilter.ModeFilter(5))
enhancer = ImageEnhance.Color(img)
enhancer.enhance(0.0) #Schwarz und weiß
enhancer.enhance(0.5) # ↕
enhancer.enhance(1.0) #Das Originalbild
enhancer = ImageEnhance.Contrast(img)
enhancer.enhance(0.0) #Graues Bild
enhancer.enhance(0.5) # ↕
enhancer.enhance(1.0) #Das Originalbild
enhancer = ImageEnhance.Brightness(img)
enhancer.enhance(0.0) #Schwarzes Bild
enhancer.enhance(0.5) # ↕
enhancer.enhance(1.0) #Das Originalbild
enhancer = ImageEnhance.Sharpness(img)
enhancer.enhance(0.0) #Verschwommenes Bild
enhancer.enhance(0.5) # ↕
enhancer.enhance(1.0) #Das Originalbild
enhancer.enhance(1.5) # ↕
enhancer.enhance(2.0) #Scharfes Bild
Das "ImageMath" -Modul ist ein Modul, mit dem Sie Operationen zwischen Pixeln schreiben können, als wären sie numerische Operationen. Wenn Sie es beherrschen, können Sie problemlos komplizierte Bildverarbeitungen schreiben.
Da nur ein einziges Band verarbeitet werden kann, ist das Konvertieren von Bildern wie RGB problematisch. Daher empfiehlt es sich, die folgende Hilfsfunktion vorzubereiten.
def _blend_f(img1, img2, func):
blend_eval = "convert(func(float(a), float(b)), 'L')"
bands = [
ImageMath.eval(
blend_eval,
a=a,
b=b,
func=func
)
for a, b in zip(img1.split(), img2.split())
]
return Image.merge(img1.mode, bands)
Implementieren Sie Zeichenmodi wie PhotoShop mit hoher Geschwindigkeit mit PIL / Pillow
def _over_lay(a, b):
_cl = 2 * a * b / 255
_ch = 2 * (a + b - a * b / 255) - 255
return _cl * (a < 128) + _ch * (a >= 128)
_blend_f(img, effect_img, _over_lay)
def _soft_light(a, b):
_cl = (a / 255) ** ((255 - b) / 128) * 255
_ch = (a / 255) ** (128 / b) * 255
return _cl * (b < 128) + _ch * (b >= 128)
_blend_f(img, effect_img, _soft_light)
def _hard_light(a, b):
_cl = 2 * a * b / 255
_ch = 2.0 * (a + b - a * b / 255.0) - 255.0
return _cl * (b < 128) + _ch * (b >= 128)
_blend_f(img, effect_img, _hard_light)
Ich erstelle ein Modul namens "Image4Layer", das den Zeichenmodus von Photoshop implementiert.
https://github.com/pashango2/Image4Layer
Die Installation ist einfach mit Pip, Kissen (PIL) muss vorinstalliert sein, um zu laufen.
$pip install image4layer
Es ist einfach zu bedienen und ein Beispiel für das Zusammensetzen im Farbausweichmodus.
from PIL import Image
from image4layer import Image4Layer
source = Image.open("ducky.png ")
backdrop = Image.open("backdrop.png ")
Image4Layer.color_dodge(backdrop, source)
Sie können mehrere GIFs (GIF-Animationen) schreiben.
im.save(out, save_all=True, append_images=[im1, im2, ...])
Dies ist ein Beispiel für die Erstellung eines einfachen animierten GIF.
imgs = []
for i in range(100):
imgs.append(img.point(lambda x: x * (1.0 - (i/100))))
img.save("anime.gif", save_all=True, append_images=imgs, loop=True)
http://pillow.readthedocs.io/en/4.0.x/handbook/image-file-formats.html?highlight=seek#saving
Beim Konvertieren von PyQt in QImage wird das Modul "ImageQt" verwendet.
ImageQt.ImageQt(img)
Wenn Sie PySide verwenden, wird die folgende Methode empfohlen.
from PySide.QtGui import *
import io
img_buffer = io.BytesIO()
base.save(img_buffer, "BMP")
qimage = QImage()
qimage.loadFromData(img_buffer.getvalue(), "BMP")
Es mag wie ein verschwenderischer Prozess erscheinen, aber Pillow / PySide kümmert sich um die problematischen Teile wie die RGB → BGR-Konvertierung und das Problem der Y-Achsen-Inversion.
Gegenseitige Konvertierung zwischen PIL.Image und PyQt4.QtGui.QImage
PSNR
Ein Indexwert, der PSNR mit zwei Bildern vergleicht. Derzeit ist SSIM besser als PSNR, aber PSNR wird auch häufig verwendet. Je höher der Wert, desto besser die Bildqualität. Bei der Messung des Grads der Verschlechterung der Komprimierung ist das PSNR zwischen 30 und 50 die Standardqualität.
Die Formel lautet wie folgt: MSE ist der durchschnittliche quadratische Fehler und MAX ist 255.
PSNR = 10 \times \log 10\frac{MAX^2}{MSE}
Die Funktion zum Auffinden von PSNR lautet wie folgt: Sie können PSNR mit hoher Geschwindigkeit finden, indem Sie das Modul "ImageStat" verwenden.
def psnr(img1, img2):
diff_img = ImageChops.difference(img1, img2)
stat = ImageStat.Stat(diff_img)
mse = sum(stat.sum2) / len(stat.count) / stat.count[0]
return 10 * math.log10(255 ** 2 / mse)
Es ist derzeit schwierig, SSIM mit PIL / Pillow mit hoher Geschwindigkeit zu finden. Verwenden Sie daher besser das Modul pyssim oder OpenCV.
[Spitzen-Signal-Rausch-Verhältnis - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%94%E3%83%BC%E3%82%AF%E4%BF%A1%E5%8F % B7% E5% AF% BE% E9% 9B% 91% E9% 9F% B3% E6% AF% 94)
gray = img.convert("L")
gray2 = gray.filter(ImageFilter.MaxFilter(5))
senga_inv = ImageChops.difference(gray, gray2)
senga = ImageOps.invert(senga_inv)
Ich bezog mich auf die Methode von hier, die sehr wunderbar ist.
Recommended Posts