PIL全稱Python Image Library,是python官方的圖像處理庫,包含各種圖像處理模塊。Pillow是PIL的一個派生分支,包含與PIL相同的功能,並且更靈活。python3.0之后,PIL不再更新,pillow代替了它原有的地位。Pillow的官方文檔:
https://pillow.readthedocs.io/en/stable/reference/index.html
在調用pillow時,代碼依然是寫成PIL,模塊導入方式如下:
from PIL import Image,ImageFilter
下面介紹基本用法。
Image
Image是pillow最基本的模塊,包含用於保存圖像對象的類。
圖像導入、旋轉、顯示、保存
from PIL import Image img = Image.open('1.jpg') img = img.rotate(45) img.show() img.save('r.jpg')
圖像導入后保存為Image對象,該對象自帶各種函數,包括圖像處理操作、顯示、保存等功能,大部分操作返回的依然是Image對象。需要注意的是,open函數執行的時候並沒有立即把圖像像素數據導入,僅僅是對圖像文件添加占用標記,直到圖像真正需要用於計算時,才會把像素數據導入。以上代碼結果如下:
Numpy.array與Image之間的轉換
Image到array
import numpy as np from PIL import Image img = Image.open('1.jpg') a = np.array(img) print(a.shape, a.dtype)
對於讀取的圖像,在Image對象中,圖像默認以RGB模式保存,且各個像素值默認用 8bit 的無符號整型來存,不論圖像以什么類型保存。因此轉換為array后dtype是uint8,不像matplotlib,png是float32,而jpg是uint8。其它圖像模式看官方文檔:
https://pillow.readthedocs.io/en/stable/handbook/concepts.html#concept-modes
array到Image
import numpy as np from PIL import Image a = np.random.random([256,256,3])*255 a = np.array(a,dtype = np.uint8) img = Image.fromarray(a) img.show()
array必須先將數據類型轉換到uint8才能轉換成Image,否則會出錯,盡管文檔中寫着能有限地支持浮點類型。
圖像模式轉換
from PIL import Image img = Image.open('1.jpg').convert('1') img.show()
以上代碼將Image模式從RGB轉換為1,也就是黑白兩色。效果如下:
圖像轉換后,Image對象所對應的像素值以及對應的數據類型也就變了。顯示的時候,Pillow會以對應的模式來顯示。可以做如下實驗,先將圖像轉變為YCbCr模式,然后分別直接顯示和轉變成array后在matplotlib中顯示,代碼如下:
import numpy as np import matplotlib.pyplot as plt from PIL import Image img = Image.open('1.jpg').convert('YCbCr') img.show() # 直接顯示 img = np.array(img) plt.imshow(img)# matplotlib中顯示 plt.axis('off') plt.show()
兩個效果分別如下:
![]() |
![]() |
可以看出,pillow 對轉換成 YCbCr 模式的圖像能以對應的模式顯示,而因為 matplotlib 是以RGB模式來顯示的,因此 YCbCr 模式的圖像會呈現右圖效果。
圖像縮放
等比例縮放
from PIL import Image size = 80,80 img = Image.open('1.jpg') img.thumbnail(size) img.show()
按等比例縮小圖像,長寬都小於等於size。需要注意的是,這個操作是直接作用與原對象上,返回為None。而通常的操作則是返回處理得到的新對象,原對象不改變,比如上面的rotate。所以這個函數的實現有點問題,和其它的特性不同,容易導致出錯,最好少用。
直接縮放
img = img.resize([128,128],Image.BICUBIC,box = (10,50,1200,1000))
三個參數分別表示:目標大小 (寬,高),采樣方式,用於縮放的圖像區域。
圖像混合
無透明通道
from PIL import Image img1 = Image.open('1.jpg') img2 = Image.open('2.jpg') img = Image.blend(img1,img2,0.5) img.show()
將兩張圖像按$\alpha : (1-\alpha)$的透明度混合,$\alpha$可以不在$(0,1)$內,結果像素值會裁剪到合理范圍內。顯示結果如下:
有透明通道
img = Image.alpha_composite(img1,img2)
其中兩張圖像必須都有$\alpha$通道。
自定義混合
import numpy as np from PIL import Image img1 = Image.open('1.jpg') img2 = Image.open('2.jpg') mask = np.ones([img1.size[1],img1.size[0]],dtype=np.uint8) mask[:,img1.size[0]//2:] *= 175 mask[:,:img1.size[0]//2] *= 80 mask = Image.fromarray(mask) img = Image.composite(img1,img2,mask) img.show()
composite函數使用mask對兩張圖像進行混合,從而不同的位置可以定義不同的透明度,以上代碼效果如下:
單像素處理
from PIL import Image import numpy as np img = Image.open('1.jpg') img = Image.eval(img, lambda x : x*np.random.rand()*2) img.show()
eval第二個參數傳入對單一像素的操作,這個操作會作用在整張圖像的每個像素值上。效果如下:
旋轉、鏡像
from PIL import Image img = Image.open('1.jpg') img = img.transpose(1) img.show()
transpose 有0~6共7個輸入,代表圖像7個旋轉、鏡像方向,加上原圖,一共8個方向。
ImageFilter
這個模塊用於圖像的濾波處理。用法也是基於Image模塊。基本用法如下:
from PIL import Image,ImageFilter img = Image.open('1.jpg') img = img.filter(ImageFilter.GaussianBlur(5)) img.show()
將ImageFilter的函數作為參數輸入filter中。還有很多種濾波方式,不一一列舉。
其它模塊
ImageEnhance:用於圖像增強,如銳化、增亮。
ImageGrab:用於截屏或讀取剪貼板獲取圖像。
ImageDraw:用於繪制簡單的線條和標記。
還有很多模塊,但感覺用起來還不如numpy+matplotlib方便,不在此記錄,有需要請看官方文檔。