1. 程式人生 > >Python 圖形處理庫PIL批量修改圖片大小和格式

Python 圖形處理庫PIL批量修改圖片大小和格式

關於PIL庫的一些概念


pil能處理的圖片型別
pil可以處理光柵圖片(畫素資料組成的的塊)。

通道
一個圖片可以包含一到多個數據通道,如果這些通道具有相同的維數和深度,Pil允許將這些通道進行疊加

模式

1  1位畫素,黑和白,存成8位的畫素
L  8位畫素,黑白
P  8位畫素,使用調色盤對映到任何其他模式
RGB  3×8位畫素,真彩
RGBA  4×8位畫素,真彩+透明通道
CMYK  4×8位畫素,顏色隔離
YCbCr  3×8位畫素,彩色視訊格式
I  32位整型畫素
F  32位浮點型畫素



尺寸
通過圖片物件的size屬性可以得到圖片的尺寸,結果這是一個二元組,包含水平和垂直方向上的畫素數。

座標


Pil採取左上角為(0,0)的座標系統

調色盤
mode("P")為每個畫素定義具體的顏色值

圖片資訊
可以通過info屬性讀取一張圖片的附加資訊,這個與圖片的格式有關。

濾鏡
在對圖片的幾何操作中可能會將多個輸入畫素對映到單個的輸出畫素,pil提供4種不同的取樣濾鏡(在目前的版本中,後續的版本可能支援更多)

NEAREST 最近
BILINEAR 雙線型
BICUBIC 雙三次插值
ANTIALIAS 平滑

在RGB模式下,每個圖片由三個通道疊加而成,每個模式下為一個灰度圖,當有一個調色盤來調色的時候,這三張灰度圖的疊加即可合成3*8位(每個畫素)的一個真彩圖片。pil庫中,圖片之間的模式(mode)可以轉化。下面給出一些簡單的例子,例子中的所有圖片均來自於國家地理的官網,為了使得文件比較短小,每個圖片均使用Pil縮放成1/2大小,如有侵權嫌疑,請儘快聯絡,我會刪除這些圖片。

所有的圖片操作必須有一個操作物件,Pil提供open(filename)

進行這個過程


開啟圖片
1.匯入pil的Image模組
2.使用open(filename)開啟檔案,返回一個image物件

Python程式碼  收藏程式碼
  1. im = Image.open('filename')  
  1. im = Image.open('filename')  


此後,一切關於圖片的操作均基於這個物件。



 

開啟後,我們可以檢視一些圖片資訊,如im.format, im.size, im.mode等。呼叫im.show()會在圖片檢視工具中顯示當前操作的image物件,這個跟個人的系統有關係,我係統中預設是用Windows Picture and Fax Viewer開啟的。這個方法用來檢視臨時的圖片效果。

讀寫圖片


pil中轉換圖片格式非常簡單(轉換圖片模式是另一個概念,不要混淆),只需要呼叫img.save(filename)即可比如有一個bmp(點陣圖)圖片,使用img = Image.open('file.bmp')開啟後,只需要img.save('file.jpg')即可轉換。不過一般情況下,save(filename)是不用做這個用途的,通常,save用以儲存一個臨時的image物件到硬碟。而轉換工作由一個功能更為強大的convert()方法來完成。


拷貝,貼上,合併

Python程式碼  收藏程式碼
  1. box = (100,100,500,500)#設定要拷貝的區域
  2. #將im表示的圖片物件拷貝到region中,大小為(400*400)畫素。這個region可以用來後續的操作(region其實就是一個Image物件),box變數是一個四元組(左,上,右,下)。
  3. region = im.crop(box)  
  4. region = region.transpose(Image.ROTATE_180)#從字面上就可以看出,先把region中的Image反轉180度,然後再放回到region中。
  5. im.paste(region, box)#貼上box大小的region到原先的圖片物件中。
  1. box = (100,100,500,500)#設定要拷貝的區域
  2. #將im表示的圖片物件拷貝到region中,大小為(400*400)畫素。這個region可以用來後續的操作(region其實就是一個Image物件),box變數是一個四元組(左,上,右,下)。
  3. region = im.crop(box)  
  4. region = region.transpose(Image.ROTATE_180)#從字面上就可以看出,先把region中的Image反轉180度,然後再放回到region中。
  5. im.paste(region, box)#貼上box大小的region到原先的圖片物件中。

 

前面說過,每一個RGB都是由三個通道的灰度圖疊加的,所以pil提供了將這三個通道分離的方法

Python程式碼  收藏程式碼
  1. r,g,b = im.split()#分割成三個通道
  2. r.show()  
  3. g.show()  
  4. b.show()  
  5. im = Image.merge("RGB", (b, g, r))#將b,r兩個通道進行翻轉。
  1. r,g,b = im.split()#分割成三個通道
  2. r.show()  
  3. g.show()  
  4. b.show()  
  5. im = Image.merge("RGB", (b, g, r))#將b,r兩個通道進行翻轉。

紅色通道的灰度圖



 綠色通道的灰度圖



 藍色通道的灰度圖

 



 
 互換紅藍通道後的合成圖

 

幾何轉變
幾何轉變提供resize,rotate等方法,用以重定義圖片大小,對圖片進行旋轉等操作,在實際應用中比較廣泛。

Python程式碼  收藏程式碼
  1. out = img.resize((128128))#resize成128*128畫素大小。
  2. out = img.rotate(45)#逆時針旋轉45度
  1. out = img.resize((128128))#resize成128*128畫素大小。
  2. out = img.rotate(45)#逆時針旋轉45度

逆時針45度



 
 鏡面效果,左右翻轉

transpose()方法預定義了一些旋轉方式,如
左右反轉,上下翻轉,逆時針旋轉(90,180,270)度等,非常方便,rotate()和transpose()方法在表現上沒有任何不同。

圖片加強


濾鏡
ImageFilter模組提供了很多預定義的圖片加強濾鏡。
比如一個常用的濾鏡,細節(detail濾鏡)

Python程式碼  收藏程式碼
  1. import ImageFilter  
  2. out = im.filter(ImageFilter.DETAIL)  
  1. import ImageFilter  
  2. out = im.filter(ImageFilter.DETAIL)  



 

直接操作畫素點
不但可以對每個畫素點進行操作,而且,每一個通道都可以獨立的進行操作。比如,將每個畫素點的亮度(不知道有沒有更專業的詞)增大20%

Python程式碼  收藏程式碼
  1. out = img.point(lambda i : i * 1.2)#注意這裡用到一個匿名函式(那個可以把i的1.2倍返回的函式)
  1. out = img.point(lambda i : i * 1.2)#注意這裡用到一個匿名函式(那個可以把i的1.2倍返回的函式)



對每個點都做20%的增強

如上邊的那個例子,我們可以將一個RGB模式的圖分離成三個通道的層

Python程式碼  收藏程式碼
  1. r,g,b = img.split()#神奇而又強大的python語法
  1. r,g,b = img.split()#神奇而又強大的python語法



然後對一個通道進行加強或減弱操作,完成後我們又可以使用Merge將通道合併,從而改變圖片的色調(冷暖色調的互換)等。

更高階的圖片加強,可以使用ImageEnhance模組,其中包含了大量的預定義的圖片加強方式。

Python程式碼  收藏程式碼
  1. import ImageEnhance  
  2. enh = ImageEnhance.Contrast(im)  
  3. enh.ehhance(1.5).show("50% more contrast")  
  1. import ImageEnhance  
  2. enh = ImageEnhance.Contrast(im)  
  3. enh.ehhance(1.5).show("50% more contrast")  

 

讀寫圖片的更多方式
通常,我們使用open方法進行圖片的開啟操作。但是這不是唯一的方式。完全可以跟python的IO整合起來。如

Python程式碼  收藏程式碼
  1. fp = open("file.jpg""rb")  
  2. im = Image.open(fp)  
  1. fp = open("file.jpg""rb")  
  2. im = Image.open(fp)  

甚至,你可以從一個字串中讀出圖片資料來(python真是神奇啊)。

Python程式碼  收藏程式碼
  1. import StringIO  
  2. img = Image.open(StringIO.StringIO(buffer))  
  1. import StringIO  
  2. img = Image.open(StringIO.StringIO(buffer))  


(文中很多內容來自pil的handbook,但是原手冊比較學院派,沒有一張圖片來進行說明,因此不免枯燥,我給每個小例子都加上一個真實的圖片作為說明,希望看起來不那沒抽象。)

當然,PIL的功能遠不止這些,由於篇幅原因,我這次先寫這麼多吧,後面會給出PIL中各個模組中函式的詳細使用說明,同時儘量配以實圖來說明。