實戰 | 用Python做影象處理(一)

七月線上實驗室發表於2018-05-23

Python中有好多工具包應用於影象處理當中,這一節(基本的影象操作和處理)作為入門章節,首先來介紹Python中最基本的幾個工具包,也希望讀者可以在之後自行練習。

PIL:Python影象處理類庫



PIL(Python Imaging Library)為影象處理類庫,它為Python提供了基本的影象處理功能和基本操作。PIL中最重要的模組又是Image,下面,我們就來講一講Image模組的一些用法。

讀取一幅影象:



我們用Image模組中的open()方法實現

首先強調一點就是對於PNG、BMP和JPG等不同格式的彩色影象之間的互相轉換都可以通過Image模組來完成,具體來說,在開啟這些影象時,PIL會將它們解碼為三通道的“RGB”影象。使用者可以基於這個“RGB”影象,對其進行處理。

from PIL import Image #從PIL包中匯入Image模組
image = Image.open('test.jpg') #讀取名為test的圖片

這是test.jpg圖片

通過上述程式碼,我們的返回值image就是一個PIL物件,當我們需要對一幅影象進行各種操作時,首先都要通過上述程式碼讀取目標影象。

上述程式碼的執行結果實際上為:

<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=1000x1436 at 0x1826BF51D68>

怎樣才能將它變為視覺化的影象呢?

我們需要呼叫matplotlib.pyplot函式集合的 imshow() 和show()方法,完整程式碼為:

from PIL import Image
import matplotlib.pyplot as plt
image = Image.open('test.jpg')
plt.imshow(image)
plt.show()# 需要呼叫show()方法,不然影象只會在記憶體中而不顯示出來

結果如下圖所示:

將影象轉換為灰度影象



 我們使用convert()方法來實現影象的灰度轉化

Convert()函式會根據傳入引數的不同將圖片變成不同的模式,通過相關資料我們知道PIL中有九種不同模式。分別為1,L,P,RGB,RGBA,CMYK,YCbCr,I,F。

模式“1”為二值影象,非黑即白。但是它每個畫素用8個bit表示,0表示黑,255表示白。

模式L”為灰色影象,它的每個畫素用8個bit表示,0表示黑,255表示白,其他數字表示不同的灰度。在PIL中,從模式“RGB”轉換為“L”模式是按照下面的公式轉換的:

L = R * 299/1000 + G * 587/1000+ B * 114/1000

模式“P”為8位彩色影象,它的每個畫素用8個bit表示,其對應的彩色值是按照調色盤查詢出來的。

模式“RGBA”為32位彩色影象,它的每個畫素用32個bit表示,其中24bit表示紅色、綠色和藍色三個通道,另外8bit表示alpha通道,即透明通道。

模式“CMYK”為32位彩色影象,它的每個畫素用32個bit表示。模式“CMYK”就是印刷四分色模式,它是彩色印刷時採用的一種套色模式,利用色料的三原色混色原理,加上黑色油墨,共計四種顏色混合疊加,形成所謂“全綵印刷”。

模式“YCbCr”為24位彩色影象,它的每個畫素用24個bit表示。YCbCr其中Y是指亮度分量,Cb指藍色色度分量,而Cr指紅色色度分量。人的肉眼對視訊的Y分量更敏感,因此在通過對色度分量進行子取樣來減少色度分量後,肉眼將察覺不到的影象質量的變化。

模式“RGB”轉換為“YCbCr”的公式如下:

Y= 0.257*R+0.504*G+0.098*B+16
Cb = -0.148*R-0.291*G+0.439*B+128
Cr = 0.439*R-0.368*G-0.071*B+128

模式“I”為32位整型灰色影象,它的每個畫素用32個bit表示,0表示黑,255表示白,(0,255)之間的數字表示不同的灰度。在PIL中,從模式“RGB”轉換為“I”模式是按照下面的公式轉換的:

I = R * 299/1000 + G * 587/1000 + B * 114/1000

模式“F”為32位浮點灰色影象,它的每個畫素用32個bit表示,0表示黑,255表示白,(0,255)之間的數字表示不同的灰度。在PIL中,從模式“RGB”轉換為“F”模式是按照下面的公式轉換的:

F = R * 299/1000+ G * 587/1000 + B * 114/1000

我們以灰度影象為例,將目標影象轉換成灰度影象,由上可知,我們要給convert()方法傳入引數“L”,具體程式碼如下:

from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.cm as cm

image = Image.open('test.jpg')  # 讀取名為test的圖片
image_gray = image.convert("L")  # 將圖片轉換為灰度影象
data = np.array(image_gray)

plt.imshow(data, cmap=cm.gray)
plt.show()

繪製出的灰度影象為:

我們也可以用一行程式碼

image = Image.open(‘test.jpg’).convert(“L”)

代替上面的兩行註釋程式碼。

在上述程式碼中我們引入了matplotlib.cm模組和numpy模組。

cm是colormap的縮寫,這個模組提供了大量的colormaps,用於註冊新的colormaps,並通過名稱獲得一個colormap,以及用於新增顏色對映功能的mixin類。

而在繪製灰度影象的imshow()方法給cmap傳入了cm.gray引數。cmap:代表顏色圖譜(colormap), 預設繪製為RGB(A)顏色空間。

為什麼調取灰度影象加了這麼一行程式碼呢?原因在於如果是彩色影象,上面的方法沒有任何問題,但是如果是灰度影象,用上面的語句就不能正確顯示,主要是沒有加調色盤。

除此之外,我們可以用一行程式碼plt.gray()來代替上述程式碼這樣寫會使程式碼看上去更加簡潔。

NumPy是一個非常有名的 Python 科學計算工具包,其中包含了大量有用的工具,比如陣列物件(用來表示向量、矩陣、影象等)以及線性代數函式。在顯示灰度影象時array()方法將影象轉換成NumPy的陣列物件,圖片得以顯示,否則會出現AttributeError的錯誤。 

轉換影象的格式



 通過save()方法,PIL可以將影象儲存成多種格式的檔案,當傳入不同的副檔名時,它會根據副檔名自動轉換影象的格式。 

from PIL import Image

image = Image.open("smallpi.jpg")  # 開啟jpg影象檔案
image.save("smallpi.png")  # 儲存影象,並轉換成png格式

下面程式從檔名列表(filelist)中讀取所有的影象檔案,並轉換成JPEG格式:

from PIL import Image
import os

for infile in filelist:
   outfile = os.path.splitext(infile)[0] + “.jpg”
   if infile != outfile:
       try:
           Image.open(infile).save(outfile)
       except IOError:
   print(‘cannot convert’, infile)

PIL的open()方法用於建立PIL影象物件,save()方法用於儲存影象到具有指定檔名的檔案,字尾變為“.jpg”,上述程式碼的新檔名和原檔名相同。PIL是個足夠智慧的類庫,可以根據副檔名來判定影象格式PIL函式會進行簡單的檢查,如果檔名不是JPEG格式,會自動將其轉為JPEG格式,如果轉換失敗,則會報錯。

建立縮圖



使用PIL可以很方便地建立影象的縮圖,thumbnail()方法接受一個一元組引數,然後將影象轉換成符合元組引數指定大小的縮圖。例如:

image.thumbnail((128,128))

thumbnail函式接受一個元組作為引數,分別對應著縮圖的寬高,在縮略時,函式會保持圖片的寬高比例。如果輸入的引數寬高和原影象寬高比不同,則會依據最小對應邊進行原比例縮放。 
比如: 
一張圖片為300*420大小的圖片 
當引數為(200,200)時,生成的縮圖大小為71*100,保持原圖的寬高比

裁剪影象區域



使用PIL中的crop()方法可以從一幅影象中裁剪指定區域,該區域使用四元組來指定,四元組的座標依次是(左,上,右,下)PIL中指定座標系的左上角座標為(0,0)。

具體程式碼為:

from PIL import Image
import matplotlib.pyplot as plt
import numpy as np

image = Image.open('test.jpg')
box = (500, 500, 1000, 1000)
region = image.crop(box)
data = np.array(region)
plt.imshow(data)
plt.show()

得到的結果為:

調整尺寸和旋轉



要調整一幅影象的尺寸,我們可以呼叫resize()方法。該方法的引數是一個元組,用來指定新影象的大小:

out = image.resize((32,32))

結果為下圖所示:

要旋轉一幅影象,可以使用逆時針方式表示旋轉角度,然後呼叫rotate()方法:

out = image.rotate(45)

結果為下圖所示:

《機器學習 第九期》從零到機器學習實戰專案,提供GPU&CPU雙雲平臺,作業考試1V1批改(優秀學員內推BAT等);點選文末“閱讀原文”瞭解詳情

相關文章