Python影象處理 Pillow 庫 基礎篇
影象處理是常用的技術,python 擁有豐富的第三方擴充套件庫,Pillow 是 Python3 最常用的影象處理庫,目前最高版本5。2。0。Python2 使用Pil庫,兩者是使用方法差不多,區別在於類的引用不同。
注意:Pil 庫與 Pillow 不能同時存在與一個環境中,如果你已經安裝 Pil 庫,那麼請將他解除安裝。
使用 pip 安裝 Pillow:
> pip install Pillow
一、使用 Image.open() 建立影象例項
Image 是 Pillow 最常用的類,他可以透過多種方式建立影象例項。
“ from PIL import Image ”匯入 Image 模組。然後透過 Image 類中的 open 函式即可載入影象檔案, open 函式會自動判斷圖片格式,只需指定檔案位置即可。成功,open 函式返回一個 Image 物件;載入檔案失敗,則會引起 IOError 異常 。
1. 透過檔案建立 Image 物件
透過檔案建立 Image 影象物件是最常用的方法
示例:透過檔案建立 Image 影象物件
from
PIL
import
Image
image
=
Image
。
open
(
‘python-logo。png’
)
# 建立影象例項
# 檢視影象例項的屬性
(
image
。
format
,
image
。
size
,
image
。
mode
)
image
。
show
()
# 顯示影象
程式碼解讀:
例項屬性說明:
format
影象格式
size
影象的 (寬,高) 元組
mode
常見模式,預設 RGB 真彩圖像;L 為灰階影象;CMYK 印刷色彩;RGBA 帶透明度的真彩圖像;YCbCr 彩色影片格式;LAB L * a * b顏色空間;HSV 等。
show()
方法為使用系統預設圖片檢視器顯示影象,一般用於除錯;
2. 從開啟檔案中讀取
可以從檔案物件讀取而不是檔名,但檔案物件必須實現 read( ) ,seek( ) 和 tell( ) 方法,並且是以二進位制模式開啟。
示例:從檔案物件中讀取影象
from
PIL
import
Image
with
open
(
“hopper。ppm”
,
“rb”
)
as
fp
:
im
=
Image
。
open
(
fp
)
2. 從 string 二進位制流中讀取
要從字串資料中讀取影象,需使用 io 類:
import
io
from
PIL
import
Image
im
=
Image
。
open
(
io
。
StringIO
(
buffer
))
注意:在讀取影象 header 之前將檔案倒回(使用 seek(0) )。
3. 從tar檔案中讀取
from
PIL
import
TarIO
fp
=
TarIO
。
TarIO
(
“Imaging。tar”
,
“Imaging/test/lena。ppm”
)
im
=
Image
。
open
(
fp
)
二、讀寫影象
1. 格式轉換並儲存影象
Image 模組中的 save 函式可以儲存圖片,除非你指定檔案格式,否則檔案的副檔名就是檔案格式。
import
os
from
PIL
import
Image
image_path
=
‘python-logo。png’
# 圖片位置
f
,
e
=
os
。
path
。
splitext
(
image_path
)
# 獲取檔名與字尾
outfile
=
f
+
“。jpg”
if
image_path
!=
outfile
:
try
:
Image
。
open
(
image_path
)
。
save
(
outfile
)
# 修改檔案格式
except
IOError
:
(
“cannot convert”
,
image_path
)
注意: 如果你的圖片mode是RGBA那麼會出現異常,因為 RGBA 意思是紅色,綠色,藍色,Alpha 的色彩空間,Alpha 是指透明度。而 JPG 不支援透明度 ,所以要麼丟棄Alpha , 要麼儲存為。png檔案。解決方法將圖片格式轉換:
Image
。
open
(
image_path
)
。
convert
(
“RGB”
)
。
save
(
outfile
)
# convert 轉換為 RGB 格式,丟棄Alpha
save() 函式有兩個引數,如果檔名沒有指定圖片格式,那麼第二個引數是必須的,他指定圖片的格式。
2. 建立縮圖
建立縮圖 使用 Image。thumbnail( size ), size 為縮圖寬長元組。
示例: 建立縮圖
import
os
from
PIL
import
Image
image_path
=
‘python-logo。png’
# 圖片位置
size
=
(
128
,
128
)
# 檔案大小
f
,
e
=
os
。
path
。
splitext
(
image_path
)
# 獲取檔名與字尾
outfile
=
f
+
“。thumbnail”
if
image_path
!=
outfile
:
try
:
im
=
Image
。
open
(
image_path
)
im
。
thumbnail
(
size
)
# 設定縮圖大小
im
。
save
(
outfile
,
“JPEG”
)
except
IOError
:
(
“cannot convert”
,
image_path
)
注意: 出現異常,同上一個示例,convert(“RGB”)轉換圖片mode。
注意:除非必須,Pillow不會解碼或柵格資料。當你開啟檔案,Pillow透過檔案頭確定檔案格式,大小,mode等資料,餘下資料直到需要時才處理。這意味著開啟檔案非常快速,它與檔案大小和壓縮格式無關。
三、剪貼,貼上、合併影象
Image類包含允許您操作影象中的區域的方法。如:要從影象中複製子矩形影象使用 crop() 方法。
1. 從影象複製子矩形
示例: 擷取矩形影象
box
=
(
100
,
100
,
400
,
400
)
region
=
im
。
crop
(
box
)
定義box元組,表示影象基於左上角為(0,0)的座標,box 座標為 (左,上,右,下)。注意,座標是基於畫素。示例中為 300 * 300 畫素。
2. 處理子矩形並將其貼上回來
示例: 在原圖上貼上子矩形影象
region
=
region
。
transpose
(
Image
。
ROTATE_180
)
# 顛倒180度
box
=
(
400
,
400
,
700
,
700
)
# 貼上位置,畫素必須吻合,300 * 300
im
。
paste
(
region
,
box
)
注意:將子圖(region) 貼上(paste)回原圖時,貼上位置 box 的畫素與寬高必須吻合。而原圖和子圖的 mode 不需要匹配,Pillow會自動處理。
示例:滾動影象
from
PIL
import
Image
def
roll
(
image
,
delta
):
“”“ 向側面滾動影象 ”“”
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
))
image
。
paste
(
part1
,
(
xsize
-
delta
,
0
,
xsize
,
ysize
))
image
。
paste
(
part2
,
(
0
,
0
,
xsize
-
delta
,
ysize
))
return
image
if
__name__
==
‘__main__’
:
image_path
=
‘test。jpg’
im
=
Image
。
open
(
image_path
)
roll
(
im
,
300
)
。
show
()
# 向側面滾動 300 畫素
3. 分離和合並通道
Pillow 允許處理影象的各個通道,例如RGB影象有R、G、B三個通道。 split 方法分離影象通道,如果影象為單通道則返回影象本身。merge 合併函式採用影象的 mode 和 通道元組為引數,將它們合併成新影象。
示例:交換RGB影象的三個波段
r
,
g
,
b
=
im
。
split
()
im
=
Image
。
merge
(
“RGB”
,
(
b
,
g
,
r
))
注意:如果要處理單色系,可以先將圖片轉換為’RGB‘
四. 幾何變換
PIL。Image。Image 包含調整影象大小 resize() 和旋轉 rotate() 的方法。前者採用元組給出新的大小,後者採用逆時針方向的角度。
示例:調整大小並逆時針旋轉 45度
out
=
im
。
resize
((
128
,
128
))
out
=
out
。
rotate
(
45
)
要以90度為單位旋轉影象,可以使用 rotate() 或 transpose() 方法。後者也可用於圍繞其水平軸或垂直軸翻轉影象。
示例:
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度
rotate() 和 transpose() 方法相同,他們之間沒有差別, transpose() 方法比較通用。
五. 顏色變換
示例:在 mode 之間轉換
from
PIL
import
Image
im
=
Image
。
open
(
“hopper。ppm”
)
。
convert
(
“L”
)
# 轉換為灰階影象
注意:它支援每種模式轉換為“L” 或 “RGB”,要在其他模式之間進行轉換,必須先轉換模式(通常為“RGB”影象)。
六. 影象增強
1. Filters 過濾器
ImageFilter 模組有很多預定義的增強過濾器,透過 filter() 方法運用。
示例:使用 filter()
from
PIL
import
ImageFilter
out
=
im
。
filter
(
ImageFilter
。
DETAIL
)
2. 畫素點處理
point() 方法可用於轉換影象的畫素值(如對比度),在大多數情況下,可以將函式物件作為引數傳遞格此方法,它根據函式返回值對每個畫素進行處理。
示例:每個畫素點擴大1。2倍
out
=
im
。
point
(
lambda
i
:
i
*
1。2
)
上述方法可以用簡單的表示式進行影象處理,還可以透過組合 point() 和 paste() 對影象的區域性區域進行處理 。
3. 處理單獨通道
# 將通道分離
source
=
im
。
split
()
R
,
G
,
B
=
0
,
1
,
2
# 選擇紅色小於100的區域
mask
=
source
[
R
]
。
point
(
lambda
i
:
i
<
100
and
255
)
# 處理綠色
out
=
source
[
G
]
。
point
(
lambda
i
:
i
*
0。7
)
# 貼上已處理的通道,紅色通道僅限於<100
source
[
G
]
。
paste
(
out
,
None
,
mask
)
# 合併影象
im
=
Image
。
merge
(
im
。
mode
,
source
)
注意建立 mask 的語句:
imout
=
im
。
point
(
lambda
i
:
expression
and
255
)
對於 and 邏輯判斷來說,expression 為 False (0) 已經能證明整個表示式為 False (0), 否則還有對後面的結果進行判斷。所以 expression 為 False (0) 返回 False (0),expression 為 True (本身的結果)是返回後面的 255;
同理對於 or 的邏輯判斷,當前面的表示式為 True,返回前面的值;當前面表示式為 False,返回後面表示式的值。
七、高階增強
其他影象增強功能可以使用 ImageEnhance 模組中的類。從影象建立後,可以使用 ImageEnhance 快速調整圖片的對比度、亮度、飽和度和清晰度。
from
PIL
import
ImageEnhance
enh
=
ImageEnhance
。
Contrast
(
im
)
# 建立調整對比度物件
enh
。
enhance
(
1。3
)
。
show
(
“增加30%對比度”
)
ImageEnhance 方法型別:
ImageEnhance。Contrast(im) 對比度
ImageEnhance。Color(im) 色彩飽和度
ImageEnhance。Brightness(im) 亮度
ImageEnhance。Sharpness(im) 清晰度
八、 動態影象
Pillow 支援一些動態影象處理(如FLI/FLC,GIF等格式)。TIFF檔案同樣可以包含數幀影象。
開啟動態影象時,PIL 會自動載入序列中的第一幀。你可以使用 seek 和 tell 方法在不同的幀之間移動。
示例: 讀取動態影象
from
PIL
import
Image
im
=
Image
。
open
(
“animation。gif”
)
im
。
seek
(
1
)
# 跳到第二幀
try
:
while
1
:
im
。
seek
(
im
。
tell
()
+
1
)
# tell() 獲取當前幀的索引號
except
EOFError
:
# 當讀取到最後一幀時,Pillow丟擲EOFError異常。
pass
# 結束
注意:有些版本的庫中的驅動程式僅允許您搜尋下一幀。要回放檔案,您可能需要重新開啟它。都遇到無法回放的庫時,可以使用 for 語句迴圈實現。
示例:for 使用 ImageSequence Iterator 類遍歷動態影象
from
PIL
import
ImageSequence
for
frame
in
ImageSequence
。
Iterator
(
im
):
# 。。。處理過程。。。
示例:儲存動態影象
im
。
save
(
out
,
save_all
=
True
,
append_images
=
[
im1
,
im2
,
。。。
])
引數說明:
out
需要儲存到那個檔案
save_all
為True,儲存影象的所有幀。否則,僅儲存多幀影象的第一幀。
append_images
需要附加為附加幀的影象列表。列表中的每個影象可以是單幀或多幀影象( 目前只有GIF,PDF,TIFF和WebP支援此功能)。
九、Postscript 列印
Pillow 允許透過 Postscript Printer 在圖片上新增影象或文字。
from
PIL
import
Image
from
PIL
import
PSDraw
im
=
Image
。
open
(
“test。jpg”
)
title
=
“hopper”
box
=
(
1
*
72
,
2
*
72
,
7
*
72
,
10
*
72
)
# in points
ps
=
PSDraw
。
PSDraw
()
# 預設 sys。stdout
ps
。
begin_document
(
title
)
# 畫出影象 (75 dpi)
ps
。
image
(
box
,
im
,
75
)
ps
。
rectangle
(
box
)
# 畫出標題
ps
。
setfont
(
“HelveticaNarrow-Bold”
,
36
)
ps
。
text
((
3
*
72
,
4
*
72
),
title
)
十、配置載入器
draft
某些解碼器允許在從檔案中讀取影象時對其進行操作。這通常可用於建立縮圖時(當速度比質量更重要)加速解碼並列印到單色鐳射印表機(僅需灰階影象時)。
draft() 方法操作已開啟但尚未載入的影象,使其儘可能匹配給定的模式和大小。它透過重新配置影象解碼器來完成。僅適用於JPEG和MPO檔案。
示例:使用 draft() 快速解碼影象
from
PIL
import
Image
im
=
Image
。
open
(
‘test。jpg’
)
(
“original =”
,
im
。
mode
,
im
。
size
)
im
。
draft
(
“L”
,
(
100
,
100
))
(
“draft =”
,
im
。
mode
,
im
。
size
)
輸出:
original
=
RGB
(
1920
,
1200
)
draft
=
L
(
240
,
150
)
注意: 生成的影象與請求的模式和大小可能不完全匹配。要確保影象不大於給定大小,需改用縮圖方法。