參考資料:Python圖像處理庫:pillowhtml
Image 類
Pillow 中最重要的類就是 Image,該類存在於同名的模塊中。能夠經過如下幾種方式實例化:從文件中讀取圖片,處理其餘圖片獲得,或者直接建立一個圖片。python
使用 Image 模塊中的 open
函數打開一張圖片:
from PIL import Image
im = Image.open('E:/Images/5a2e2075f331d.png')
im
若是打開成功,返回一個 Image 對象,能夠經過對象屬性檢查文件內容:數組
print(im.format, im.size, im.mode)
PNG (1920, 1080) RGBA
format
屬性定義了圖像的格式(PNG
,JPG
,None
),若是圖像不是從文件打開的,那麼該屬性值爲None
;size
屬性是一個二元tuple
,表示圖像的寬和高(單位爲像素px
);mode
屬性爲表示圖像的模式,經常使用的模式爲:L
(luminance)爲灰度圖,RGB
爲真彩色,CMYK
爲 pre-press 圖像。官方說明-圖像模式完整列表palette
: 僅當 mode 爲 P 時有效,返回 ImagePalette 實例info
: 以字典的形式返回實例的信息
若是文件不能打開,則拋出 IOError
異常。網絡
當有一個 Image
對象時,能夠用 Image
類的各個方法進行處理和操做圖像:ide
讀寫圖片
Pillow 庫支持至關多的圖片格式。直接使用 Image 模塊中的 open()
函數讀取圖片,而沒必要先處理圖片的格式,Pillow 庫自動根據文件決定格式。 Image 模塊中的 save()
函數能夠保存圖片,除非你指定文件格式,那麼文件名中的擴展名用來指定文件格式。函數
例子:轉換圖像格式的腳本(jpg
轉爲 png
格式)spa
im.save('E:/Images/5a2e2075f331d.png', 'jpeg')
import os
root = 'E:/Images/'
for name in os.listdir(root): infile = root + name f, e = os.path.splitext(infile) # f 變量是除擴展名之外的文件名,e 變量是擴展名 if os.path.isfile(infile): outfile = f +".png" # 拼湊輸出文件名 print(f) if infile != outfile: # 保存的圖像格式跟原圖像格式不同 try: Image.open(infile).save(outfile) # 轉換圖像格式 except IOError: print("Cannot convert", infile) # 圖像沒法打開,則處理異常
E:/Images/5a2e206693e4d E:/Images/5a2e2075f331d E:/Images/psb E:/Images/psb1 E:/Images/README Cannot convert E:/Images/README.md E:/Images/thIZ7ILLM5 E:/Images/thO3CXS0S3 E:/Images/water
建立縮略圖
縮略圖是網絡開發或者圖像軟件預覽經常使用的一種基本技術,使用 Python 的 Pillow 圖像庫能夠很方便地創建縮略圖。3d
Image 類的 thumbnail()
方法能夠用來製做縮略圖。它接受一個二元數組做爲縮略圖的尺寸,而後將實例縮小到指定尺寸。code
例子:生成 JPEG
縮略圖,大小是原圖像的四分之一orm
for name in os.listdir(root): infile = root + name if os.path.isfile(infile): outfile = os.path.splitext(infile)[0] + ".thumbnail" # 縮略圖文件名+後綴 if infile != outfile: try: im = Image.open(infile) # 打開圖像 x, y = im.size # 獲取原圖像的大小(width、height) im.thumbnail((x//2, y//2)) # 縮略圖大小 im.save(outfile, "JPEG") # 保存爲 JPEG 格式 except IOError: print("cannot create thumbnail for", infile)
cannot create thumbnail for E:/Images/5a2e206693e4d.png cannot create thumbnail for E:/Images/5a2e2075f331d.png cannot create thumbnail for E:/Images/README.md
注意:Pillow 庫不會直接解碼或者加載圖像柵格數據。當你打開一個文件,只會讀取文件頭信息用來肯定格式,顏色模式,大小等等,文件的剩餘部分不會主動處理。這意味着打開一個圖像文件的操做十分快速,跟圖像大小和壓縮方式無關。
圖像的剪切、粘貼與合併操做
Image 類包含不少操做圖像區域的方法。
裁剪子矩形
crop()
方法能夠從圖像中提取一個子矩形選區,以下:
im = Image.open('E:/Images/5a2e2075f331d.png') box = (80, 80, 300, 300) region = im.crop(box) region
矩形選區區域由一個 $4$ 元元組決定,元組信息表示 (左,上,右,下)
的座標。Pillow 庫以圖像左上角爲座標原點 $(0,0)$,單位是 px
。 所以,上述代碼是複製了一個 $220 \times 220$ pixels 的矩形選區。
處理子圖,粘貼回原圖
region = region.transpose(Image.ROTATE_270) # 旋轉180° im.paste(region, box) im
transpose()
方法能夠將圖片左右顛倒、上下顛倒、旋轉 $90°$、旋轉 $180°$ 或旋轉 $270°$。paste()
方法則能夠將一個 Image 實例粘貼到另外一個 Image 實例上。
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)) # 右邊矩形選區 part1.load() part2.load() image.paste(part2, (0, 0, xsize-delta, ysize)) # 原右邊圖形貼到左邊 image.paste(part1, (xsize-delta, 0, xsize, ysize)) # 原左邊圖形貼到右邊 return image im = Image.open('E:/Images/5a2e2075f331d.png') print(im.size) # (356, 362) roll(im,100).save('E:/Images/5a2e2075f331d.png','JPEG')
(450, 675)
im
要注意的是,當你使用 crop()
方法來修改圖像文件的時候, load()
方法會首先被調用。這是因爲修改是一個惰性操做。若是 load()
未被調用,那麼在 paste
使用前都不會執行修改這個操做。這暗示着 part1
會在首次修改 image
的時候被修改。
分離和合並顏色通道
對於多通道圖像,有時候處理時但願可以分別對每一個通道處理,處理完成後從新合成多通道,以下:
r, g, b = im.split() im = Image.merge('RGB', (r, g, b))
對於 split()
函數,若是是單通道的,則返回其自己。不然,返回各個通道。
幾何變換
Image 類包含了 resize()
和 rotate
方法來變換圖像。前者須要傳入一個表示新大小的元組,後者須要傳入旋轉的角度。
簡單的幾何變換
out = im.resize((128, 128)) out
rout = out.rotate(45) # 順時針角度表示 rout
旋轉圖像
out = im.transpose(Image.FLIP_LEFT_RIGHT) # 左右顛倒 out = im.transpose(Image.FLIP_TOP_BOTTOM) # 上下顛倒 out = im.transpose(Image.ROTATE_90) # 旋轉90° out = im.transpose(Image.ROTATE_180) # 旋轉180° out = im.transpose(Image.ROTATE_270) # 旋轉270°
更通用的圖像變換方法能夠使用 transform()
ImageDraw模塊
ImageDraw 模塊提供了 Draw
類,它能在 Image
實例上進行簡單的 2D 繪畫。你能夠使用這個模塊來建立新圖像或者修飾現有圖像。
有關 PIL 的更高級繪圖庫,能夠參考 aggdraw模塊
建立 Draw 類的實例
要在 Image 實例上繪製新的圖樣,首先要建立一個 Draw
類的實例。
這裏粗略介紹下 Draw 類中的基本繪畫操做函數(英文都是函數名):
- 弦/弧/扇形:
chord
/arc
/pieslice
- 橢圓:
ellipse
- 線段/多段線:
line
- 點:
point
- 多邊形:
polygon
- 矩形:
rectangle
- 文字:
text
- 文字大小:
textsize
詳細的使用說明,請看官方文檔:Draw 類的各函數使用說明
畫直線
Draw 類提供了 line(xy,options)
函數繪製直線。 其中 xy
表示座標列表,它能夠是任何包含 $2$ 元組 [(x,y),…]
或者數字 [x,y,…]
的序列對象,至少包含兩個座標:
[(x1, y1), (x2, y2), …]
:包含若干個元組的列表[x1, y1, x2, y2, …]
:按照順序包含座標信息的列表[x1, y1, (x2, y2), …]
:以上兩種狀況的混合((x1, y1), (x2, y2), …)
:包含若干個元組的元組(x1, y1, x2, y2, …)
:按照順序包含座標信息的元組(x1, y1, (x2, y2), …)
:以上兩種狀況的混合options
可用的選項:fill = (R,G,B)
:指定線條顏色width = integer
:指定線條寬度,單位是px
from PIL import Image,ImageDraw im = Image.open('E:/Images/5a2e2075f331d.png') drawAvatar = ImageDraw.Draw(im) xSize,ySize = im.size # 三等分位置 drawAvatar.line([0, 0.33 * ySize, xSize, 0.33 * ySize],\ fill = (255, 100, 0), width = 3) # 左下角到中心點,右下角到中心點 drawAvatar.line([(0, ySize), (0.5 * xSize, 0.5 * ySize), (xSize, ySize)],\ fill = (255, 0, 0), width = 3) im.save('E:/Images/5a2e2075f331d.jpg')
參考資料: