Pillow快速入門
前言
本教程目的
學習該庫,目的是爲了用python
去操作圖像提供更爲全面的選擇。
本庫進階學習
進階學習,首先需要很明確瞭解要對圖像進行什麼操作,然後查詢相關的API
。
初學思維導圖
接下來就是初學者教程。
使用 Image
Class
在PIL
中,最重要的類就是Image
這個和模塊名相同的類。您可以通過多種方式創建該類的實例;要麼從文件中加載圖像,要麼處理其他圖像,要麼從頭創建圖像。
要從文件中加載圖像,請使用圖像模塊中的open()函數:
from PIL import Image
im = Image.open("hopper.ppm")
如果成功,此函數將返回一個圖像對象。你現在可以使用實例屬性來檢查文件內容:
print(im.format, im.size, im.mode)
# PPM (512, 512) RGB
讀寫圖像
Python圖像庫支持多種圖像文件格式。要從磁盤讀取文件,請使用圖像模塊中的open()函數。你不必知道打開一個文件的格式。庫根據文件的內容自動確定格式。
保存目標格式的圖像
import os, sys
from PIL import Image
for infile in sys.argv[1:]:
f, e = os.path.splitext(infile)
outfile = f + ".jpg"
if infile != outfile:
try:
with Image.open(infile) as im:
# 核心是im.save()
im.save(outfile)
except IOError:
print("cannot convert", infile)
創建縮略圖
import os, sys
from PIL import Image
size = (128, 128)
for infile in sys.argv[1:]:
outfile = os.path.splitext(infile)[0] + ".thumbnail"
if infile != outfile:
try:
with Image.open(infile) as im:
#此處在緩衝區生成size大小的thumbnail()
im.thumbnail(size)
im.save(outfile, "JPEG")
except IOError:
print("cannot create thumbnail for", infile)
需要注意的是,除非必要,否則庫不會解碼或加載光柵數據。當您打開一個文件時,將讀取文件頭以確定文件格式,並提取解碼文件所需的模式、大小和其他屬性,但是文件的其餘部分直到稍後才處理。
識別一系列的文件
import sys
from PIL import Image
for infile in sys.argv[1:]:
try:
# 每次打開一張圖像並且對其做以釋放
with Image.open(infile) as im:
print(infile, im.format, "%dx%d" % im.size, im.mode)
except IOError:
pass
裁剪、複製、拼接圖像
從圖像中複製子矩形
box = (100, 100, 400, 400)
region = im.crop(box)
區域由一個4元組定義,其中的座標是(左、上、右、下)。Python圖像庫使用左上角的座標系統(0,0)。還要注意,座標是指像素之間的位置,所以上面例子中的區域就是300x300像素。
現在可以以某種方式處理該區域並將其粘貼回去。
處理子矩形,並將其粘貼回去
region = region.transpose(Image.ROTATE_180)
im.paste(region, box)
當粘貼區域時,區域的大小必須與給定的區域完全匹配。此外,區域不能延伸到圖像之外。但是,原始圖像的模式和區域不需要匹配。如果沒有,則在粘貼之前自動轉換區域。
平移和拼接圖像
def roll(image, delta):
"""Roll an image sideways."""
xsize, ysize = image.size
delta = delta % xsize
if delta == 0: return image
part1 = image.crop((0, 0, delta, ysize))
part2 = image.crop((delta, 0, xsize, ysize))
image.paste(part1, (xsize-delta, 0, xsize, ysize))
image.paste(part2, (0, 0, xsize-delta, ysize))
return image
對於更高級的技巧,paste方法還可以將透明蒙版作爲可選參數。
在這個掩碼中,值255表示粘貼後的圖像在那個位置是不透明的(即,應該按原樣使用粘貼後的圖像)。值0表示粘貼的圖像是完全透明的。中間值表示不同的透明度級別。例如,粘貼RGBA圖像並將其用作掩碼將粘貼圖像的不透明部分,但不粘貼其透明的背景。
Python圖像庫還允許您處理多波段圖像的單個波段,例如RGB圖像。分割方法創建一組新圖像,每個圖像包含原始多頻帶圖像中的一個頻帶。merge函數接受一個模式和一個圖像元組,並將它們組合成一個新圖像。下面的例子交換了一個RGB圖像的三個波段:
分割和融合波段信息
r, g, b = im.split()
im = Image.merge("RGB", (b, g, r))
注意,對於單波段圖像,split()返回圖像本身。要使用單獨的顏色帶,您可能需要首先將圖像轉換爲“RGB”。
幾何變換
PIL.Image。Image類包含調整()和旋轉()圖像的方法。前者採用一個元組提供新的大小,而後者採用逆時針角度。
簡單的幾何變換
out = im.resize((128, 128))
out = im.rotate(45) # degrees counter-clockwise
要將圖像旋轉90度,可以使用rotate()方法或轉置()方法。後者也可以用來翻轉圖像的水平或垂直軸。
翻轉圖像
out = im.transpose(Image.FLIP_LEFT_RIGHT)
out = im.transpose(Image.FLIP_TOP_BOTTOM)
out = im.transpose(Image.ROTATE_90)
out = im.transpose(Image.ROTATE_180)
out = im.transpose(Image.ROTATE_270)
transpose(ROTATE)
操作也可以和rotate
進行相同的操作。
如果expand
爲True
則原圖像做相應的修改。
更加通用的操作是通過transform()
方法對其進行修改。
顏色(通道)轉換
Python圖像庫允許您使用convert()方法在不同的像素表示之間轉換圖像。
模式之間的轉換
from PIL import Image
with Image.open("hopper.ppm") as im:
im = im.convert("L")
該庫支持在每個支持模式與“L”和“RGB”模式之間進行轉換。要在其他模式之間進行轉換,您可能必須使用中間圖像(通常是“RGB”圖像)。
圖象增強
Python圖像庫提供了許多可以用來增強圖像的方法和模塊。
濾波
imageFilter
模塊包含許多預定義的增強過濾器,可以與filter()方法一起使用.
from PIL import ImageFilter
out = im.filter(ImageFilter.DETAIL)
像素操作
point()方法可用於轉換圖像的像素值(例如,圖像對比度處理)。在大多數情況下,期望一個參數的函數對象可以傳遞給這個方法。每個像素按照該函數進行處理:
對點進行操作
# multiply each pixel by 1.2
out = im.point(lambda i: i * 1.2)
使用上述技術,您可以快速地將任何簡單的表達式應用於圖像。您還可以組合使用point()和paste()方法來選擇性地修改圖像:
處理單個波段
# split the image into individual bands
source = im.split()
R, G, B = 0, 1, 2
# select regions where red is less than 100
mask = source[R].point(lambda i: i < 100 and 255)
# process the green band
out = source[G].point(lambda i: i * 0.7)
# paste the processed band back, but only where red was < 100
source[G].paste(out, None, mask)
# build a new multiband image
im = Image.merge(im.mode, source)
注意用於創建掩碼的語法:
imout = im.point(lambda i: expression and 255)
圖像增強
對於更高級的圖像增強,您可以使用ImageEnhance
模塊中的類。從圖像創建後,可以使用增強對象快速嘗試不同的設置。
你可以通過這種方式調整對比度、亮度、色彩平衡和銳度。
from PIL import ImageEnhance
enh = ImageEnhance.Contrast(im)
enh.enhance(1.3).show("30% more contrast")
圖像序列
Python圖像庫包含對圖像序列(也稱爲動畫格式)的一些基本支持。支持的序列格式包括FLI/FLC、GIF和一些實驗格式。TIFF文件也可以包含一個以上的幀。
當你打開一個序列文件時,PIL會自動加載序列中的第一幀。你可以使用查找和告訴方法在不同的幀之間移動:
序列讀取
from PIL import Image
with Image.open("animation.gif") as im:
im.seek(1) # skip to the second frame
try:
while 1:
im.seek(im.tell()+1)
# do something to im
except EOFError:
pass # end of sequence
使用ImageSequence
迭代器類
from PIL import ImageSequence
for frame in ImageSequence.Iterator(im):
# ...do something to frame...
圖像打印
Python圖像庫包括在Postscript打印機上打印圖像、文本和圖形的函數。這裏有一個簡單的例子:
from PIL import Image
from PIL import PSDraw
with Image.open("hopper.ppm") as im:
title = "hopper"
box = (1*72, 2*72, 7*72, 10*72) # in points
ps = PSDraw.PSDraw() # default is sys.stdout
ps.begin_document(title)
# draw the image (75 dpi)
ps.image(box, im, 75)
ps.rectangle(box)
# draw title
ps.setfont("HelveticaNarrow-Bold", 36)
ps.text((3*72, 4*72), title)
ps.end_document()
關於讀取圖像
我們可以使用上下文管理器去讀取圖像進行一系列的操作:
from PIL import Image
with Image.open("hopper.ppm") as im:
...
您可以使用類似文件的對象來代替文件名。該對象必須實現read()、seek()和tell()方法,並以二進制模式打開。
從打開的文件中讀取圖像
from PIL import Image
with open("hopper.ppm", "rb") as fp:
im = Image.open(fp)
從二進制文件中讀取
要從二進制數據中讀取圖像,使用BytesIO
類:
from PIL import Image
import io
im = Image.open(io.BytesIO(buffer))
從壓縮文件中讀取圖像
注意,庫在讀取圖像頭之前會回滾文件(使用seek(0))。此外,在讀取圖像數據時也將使用seek(通過load方法)。如果圖像文件嵌入到更大的文件中,例如tar文件,則可以使用ContainerIO
或TarIO
模塊來訪問它。
from PIL import Image, TarIO
fp = TarIO.TarIO("Tests/images/hopper.tar", "hopper.jpg")
im = Image.open(fp)
控制編碼器
一些解碼器允許您在從文件中讀取圖像時操作圖像。當創建縮略圖(速度通常比質量更重要)和在單色激光打印機上打印(只需要圖像的灰度版本)時,這通常可以用來加快解碼速度。
draft()
方法操作打開但尚未加載的圖像,使其儘可能接近給定的模式和大小。這是通過重新配置圖像解碼器實現的。
使用draft()
讀取圖像
這隻在JPEG
和MPO
文件情況下適用。此方法操作打開但尚未加載的圖像,使其儘可能接近給定的模式和大小。
from PIL import Image
with Image.open(file) as im:
print("original =", im.mode, im.size)
im.draft("L", (100, 100))
print("draft =", im.mode, im.size)
"""
輸出:
original = RGB (512, 512)
draft = L (128, 128)
"""
注意,生成的圖像可能與請求的模式和大小不完全匹配。要確保圖像不大於給定的大小,請使用縮略圖方法。