1. 程式人生 > 程式設計 >影象處理庫 pillow(二)

影象處理庫 pillow(二)

上節我們講了 Python 的影象處理庫 PIL 的基本影象處理功能,開啟了 PIL 的神祕面紗。這節我們接著講 PIL 的 Image 模組的常用方法。

Image 模組的方法

convert

Image.convert(mode=None,matrix=None,dither=None,palette=0,colors=256)

引數說明:

  • mode:轉換的模式
  • matrix:可選轉變矩陣。如果給出,必須為包含浮點值長為 4 或 12 的元組。
  • dither:抖動方法。RGB 轉換為 P;RGB 或 L 轉換為 1 時使用。有 matrix 引數可以無 dither。引數值 NONE 或 FLOYDSTEINBERG(預設)。
  • palette:調色盤,在 RGB 轉換為 P 時使用, 值為 WEB 或 ADAPTIVE 。
  • colors:調色盤的顏色值,預設 256.

轉換圖片模式,它支援每種模式轉換為"L" 、 "RGB"和 "CMYK"。 有 matrix 引數只能轉換為"L" 或 "RGB"。 當模式之間不能轉換時,可以先轉換 RGB 模式,然後在轉換。 色彩模式轉換為 L 模式計算公式 如下:

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

我們一般使用時,只用傳需要轉換的 mode 即可,其他的可選引數需要先理解圖片深層次的原理後才可以理解,大家如果感興趣可以去深入瞭解一下。下面我們來看一個簡單例項:

from PIL import Image

im = Image.open('cat.png')
im.show()
# 將影象轉換成黑白色並返回新影象
im1 = im.convert('L')
im1.show()
複製程式碼

我們將一個影象轉換成 L模式(灰色),轉換結果如下圖所示:

image-convert.png

copy

Image.copy()

複製影象方法,該方法完全複製一個一模一樣的影象,很好理解,我們就不舉例說明瞭。

crop

Image.crop(box)

引數說明:

  • box:相對影象左上角座標為(0,0)的矩形座標元組,順序為(左,上,右,下)

該方法從影象中獲取 box 矩形區域的影象,相當於從影象中摳一個矩形區域出來。我們來看例子:

from PIL import Image

im = Image.open('cat.jpg')
print(im.size)
im.show()

# 定義了影象的座標位置,從左、上、右、下
box = (100,100,250,250)

# 它會從左上角開始,同時向下和向右移動100畫素的位置開始擷取250-100的畫素寬高,也就是150x150的影象
# 這裡注意後兩個數值要大於前兩個數值,不然擷取後的影象寬高為負數,會報錯
region = im.crop(box)
print(region.size)
region.show()

# 輸出結果
(451,300)
(150,150)
複製程式碼

我們從 cat.jpg 這張圖片中截取了 150x150 的影象,從列印結果可以看到擷取前和擷取後的影象大小。兩張影象的對比如下圖:

image-crop.png

filter

Image.filter(filter)

引數說明:

  • filter:過濾核心

使用給定的篩選器篩選此影象。有關可用篩選器的列表:

篩選器名稱 說明
BLUR 模糊濾波,處理之後的影象會整體變得模糊。
CONTOUR 輪廓濾波,將影象中的輪廓資訊全部提取出來。
DETAIL 細節增強濾波,會使得影象中細節更加明顯。
EDGE_ENHANCE 邊緣增強濾波,突出、加強和改善影象中不同灰度區域之間的邊界和輪廓的影象增強方法。
EDGE_ENHANCE_MORE 深度邊緣增強濾波,會使得影象中邊緣部分更加明顯。
EMBOSS 浮雕濾波,會使影象呈現出浮雕效果。
FIND_EDGES 尋找邊緣資訊的濾波,會找出影象中的邊緣資訊。
SHARPEN 銳化濾波,補償影象的輪廓,增強影象的邊緣及灰度跳變的部分,使影象變得清晰。
SMOOTH 平滑濾波,突出影象的寬大區域、低頻成分、主幹部分或抑制影象噪聲和幹擾高頻成分,使影象亮度平緩漸變,減小突變梯度,改善影象質量。
SMOOTH_MORE 深度平滑濾波,會使得影象變得更加平滑。

看到這些,大家是不是聯想到我們手機上一些 APP 的影象處理功能了,其實那些功能的實現方式跟我們這裡講的方法是一樣的。我們來看個例子:

from PIL import Image
from PIL import ImageFilter

im = Image.open('flower.jpg')
im.show()

# 模糊
im2 = im.filter(ImageFilter.BLUR)
im2.show()

# 輪廓濾波
im3 = im.filter(ImageFilter.CONTOUR)
im3.show()

# 細節增強
im4 = im.filter(ImageFilter.DETAIL)
im4.show()
複製程式碼

我們分別對原圖了使用了模糊濾波、輪廓濾波、細節增強濾波的處理,大家執行程式就可以看到處理後的效果了,如下圖所示:

image-filter.png

getbands

Image.getbands()

返回一個包含此影象中每個通道名稱的元組。直接看例項:

from PIL import Image

# 開啟影象
im = Image.open('cat.jpg')
# 建立新影象
im1 = Image.new('L',(450,450),50)

# 獲取影象的通道名稱元組
print(im.getbands())
print(im1.getbands())

# 輸出結果
('R','G','B')
('L',)
複製程式碼

上例中,我們分別開啟一個 RGB 影象和建立一個 L 模式的新影象,然後列印輸出他們的通道名稱。

getbbox

Image.getbbox()

計算影象中非零區域的邊界框。將邊界框作為定義左、上、右和下畫素座標的四元組返回。我們來看例子:

from PIL import Image

# 開啟影象(451x300)
im = Image.open('cat.jpg')
# 建立新影象(450x450)
im1 = Image.new('L',50)

# 列印影象中非零區域的邊界框
print(im.getbbox())
print(im1.getbbox())

# 輸出結果
(0,451,300)
(0,450,450)
複製程式碼

這個方法很簡單,很容易理解,那麼這個方法有什麼用處呢?最直接的一個用處就是迅速地獲取影象的邊界座標。

getcolors

Image.getcolors(maxcolors=256)

引數說明:

  • maxcolors:最大顏色數。預設限制為256色。

獲取影象中顏色的使用列表,超過 maxcolors 設定值返回 None 。 返回值為 (count,pixel) 的列表,表示(出現的次數,畫素的值)

from PIL import Image

im = Image.open('cat.png')

# 將彩色影象轉換成灰度圖
im2 = im.convert("L")

# 列印灰度圖的顏色列表,返回的點數超過maxcolors就直接返回None
print(im2.getcolors(maxcolors=200))
print(im2.getcolors(maxcolors=255))

# 輸出結果
None
[(1,0),(69,1),(275,2),(518,3),(165,4),... (6,250),(1,251)]
複製程式碼

我們這個影象有252個畫素值,所以第一次 maxcolors 設定為200時,由於 252>200,所以返回了 None。第二次設定255時,正常返回。

getdata

Image.getdata(band=None)

引數:

  • band:獲取對應通道值。如:RGB 影象畫素值為 (r,g,b) 的元組,要返回單個波段,請傳遞索引值(例如0,從 RGB 影象中獲取 R 波段)。

獲取影象中每個畫素的通道物件元組,畫素獲取從左至右,從上至下。

getextrema

Image.getextrema()

獲取影象中每個通道的最小值與最大值。對於單波段影象,包含最小和最大畫素值的2元組。對於多波段影象,每個波段包含一個2元組的元組。

getpixel

Image.getpixel(xy)

引數:

  • xy:座標,以(x,y)表示。

通過傳入座標返回畫素值。如果影象是多層影象,則此方法返回元組。

point

Image.point(lut,mode=None)

引數說明:

  • lut:一個查詢表,包含影象中每個波段的256個(或65536個,如果 self.mode==“I” 和 mode==“L”)值。可以改用函式,它應採用單個引數。對每個可能的畫素值呼叫一次函式,結果表將應用於影象的所有帶區。

  • mode:輸出模式(預設與輸入相同)。只有當源影象具有模式 “L” 或 “P” ,並且輸出具有模式 “1” 或源影象模式為 “I” ,並且輸出模式為 “L” 時,才能使用此選項。

對影象的的每個畫素點進行操作,返回影象的副本。

from PIL import Image

im = Image.open('cat.png')

# 調整灰色影象的對比度
im_point=im.convert('L').point(lambda i: i < 80 and 255)
im_point.show()

source = im.split()
# 三通道分別處理對比度
band_r = source[0].point(lambda i: i < 80 and 255)
band_g = source[1].point(lambda i: i < 80 and 255)
band_b = source[2].point(lambda i: i < 80 and 255)
band_r.show()
band_g.show()
band_b.show()
複製程式碼

在例子中,我們先將影象轉換成 L 模式,然後調整對比度,以及將影象的三個通道分別調整對比度。所謂調整對比度,我們這個例子的規則就是當畫素值小於80時,將其調整為255,相當於將接近黑色的畫素點加黑,使其與淺色對比更明顯。執行效果如下圖:

image-point.png

resize

Image.resize(size,resample=0,box=None)

引數說明:

  • size:以畫素為單位的請求大小,作為2元組:(寬度、高度)。
  • resample:可選的重新取樣濾波器。可以是 PIL.Image.NEAREST(最近濾波) , PIL.Image.ANTIALIAS (平滑濾波), PIL.Image.BILINEAR (雙線性濾波), PIL.Image.HAMMING , PIL.Image.BICUBIC (雙立方濾波)。如果省略,或者影象具有模式 “1” 或 “P” ,則設定為 PIL.Image.NEAREST 。 -box:一個可選的4元組的浮點數,給出了應該縮放的源影象區域。值應在(0,0,寬度,高度)矩形內。如果省略或沒有,則使用整個源。

這個方法是獲取調整大小後的圖片。通俗地講就是在原圖中摳一個矩形區域(如果傳入了 box 引數),然後對摳出來的區域進行濾波處理(如果傳入了 resample 引數),最後以指定的 size 大小進行返回。

from PIL import Image

im = Image.open('flower.jpg')

img1 = im.resize((250,Image.BILINEAR)
img2 = im.resize((250,Image.BICUBIC)
img3 = im.resize((250,Image.NEAREST)

im.show()
img1.show()
img2.show()
img3.show()
複製程式碼

這幾個濾波器的具體的原理比較理論,大家對照著程式執行返回自行去深入瞭解。

關於 PIL 的 Image 模組的方法我們只講這麼多,還有好多其他方法,大家可參照 www.osgeo.cn/pillow/refe… 這個網站去嘗試。

我們講的 PIL 的 Image 模組只是 PIL 的一個基礎模組而已,它還有好多其他的模組,諸如 ImageChops (通道操作模組)、ImageColor (顏色轉換模組)、ImageDraw (二維圖形模組)等,大家在需要的時候可以去查詢 API 使用。

總結

pillow 庫是一個非常強大的基礎影象處理庫,若不深入影象處理,運用這個庫裡面的方法組合,對影象進行各種常見的操作已經夠用,這是計算機圖片識別的基礎。當然,如果需要更專業的操作,那麼就直接上 opencv 吧。

參考

www.osgeo.cn/pillow/refe…