摘要:本文簡單介紹了用Python來完成簡單影像處理任務的方法。雖然影像處理的最佳工具是MATLAB的影像處理工具箱,但是在進行一些“簡單的”影像處理任務或者大批量的簡單影像處理任務的時候,Python更有優勢。
關鍵詞:影像處理 映像增強 Python
Abstract:This context introduces some methods used to fullfill simply image processing task in python programming language.Although the best image processing toolkit is the Image Processing Toolbox of MATLAB,python is superior to this toolkit when your staff is somewhat “simple” or simple but boring and exhausting image processing commitment.
Keywords:Image Processing Image Enhancement Python
1.引言:
提到影像處理,人們通常想到的工具是MATLAB。誠然,MATLAB提供了一個強大的影像處理工具箱。但是,對於簡單的影像處理任務而言,採用一種進階的語言將起到事半功倍的效果。Python無疑就是實現這一功能的理想選擇。Python的物件導向、弱資料類型等等特性都使得用它來進行簡單的影像處理的時候非常的簡潔方便。
2.簡介:
PythonWare公司提供了免費的影像處理工具包PIL(Python Image Library),該軟體包提供了基本的影像處理功能,如:改變映像大小,旋轉映像,映像格式轉換,色場空間轉換,映像增強,長條圖處理,插值和濾波等等。雖然在這個軟體包上要實作類別似MATLAB中的複雜的影像處理演算法並不太適合,但是Python的快速開發能力以及物件導向等等諸多特點使得它非常適合用來進行原型開發。
在PIL中,任何一副映像都是用一個Image對象表示,而這個類由和它同名的模組匯出,因此,要載入一副映像,最簡單的形式是這樣的:
import Image
img = Image.open(“dip.jpg”)
注意:第一行的Image是模組名;第二行的img是一個Image對象; Image類是在Image模組中定義的。關於Image模組和Image類,切記不要混淆了。現在,我們就可以對img進行各種操作了,所有對img的操作最終都會反映到到dip.img映像上。
PIL提供了豐富的功能模組:Image,ImageDraw,ImageEnhance,ImageFile等等。最常用到的模組是Image,ImageDraw,ImageEnhance這三個模組。下面我對此分別做一介紹。關於其它模組的使用請參見說明文檔.有關PIL軟體包和相關的說明文檔可在PythonWare的網站www.pythonware.com上獲得。
3.Image模組:
Image模組是PIL最基本的模組,其中匯出了Image類,一個Image類執行個體對象就對應了一副映像。同時,Image模組還提供了很多有用的函數。
(1)開啟一副影像檔:
import Image
img = Image.open(“dip.jpg”)
這將返回一個Image類執行個體對象,後面的所有的操作都是在img上完成的。在這裡,我們讀入的映像是:
(2)調整映像大小:
import Image
img = Image.open("img.jpg")
new_img = img.resize((128,128),Image.BILINEAR)
new_img.save("new_img.jpg")
原來的映像大小是256x256,現在,儲存的new_img.jpg的大小是128x128:
就是這麼簡單,需要說明的是Image.BILINEAR指定採用雙線性法對像素點插值。
(3)旋轉映像:
現在我們把剛才調整過大小的映像旋轉45度:
import Image
img = Image.open("img.jpg")
new_img = img.resize((128,128),Image.BILINEAR)
rot_img = new_img.rotate(45)
rot_img.save("rot_img.jpg")
於是我們儲存到rot_img.jpg的映像看起來像下面這樣:
(4)格式轉換:
假設我們要把上面產生的rot_img.jpg轉換成bmp映像,要做到這一點這太簡單了:只需要在上面的代碼後面添加下面這樣一行即可:
rot_img.save("con_img.bmp")
如果不指定儲存格式,PIL將自動根據檔案名稱尾碼完成格式之間的轉換,是不是很簡單呢?
(5)長條圖統計:
Image類執行個體的histogram()方法能夠對長條圖資料進行統計,並將結果做為一個列表(list)返回。比如,我們對上面的旋轉後產生的映像進行長條圖統計:
import Image
img = Image.open("img.jpg")
new_img = img.resize((128,128),Image.BILINEAR)
rot_img = new_img.rotate(45)
print rot_img.histogram()
運行之後將列印出所有256個灰階級像素點個數的統計值:
[2819, 22, 82, 119, 186, 204, 212, 218, 223, 200, 151, 103, 129, 74, 80, 83, 110, 70, 59, 64, 59, 58, 35, 45, 42, 38, 32, 39, 33, 19, 24, 26, 32, 17, 33, 24, 34, 19, 18, 15, 11, 23, 16, 15, 21, 13, 20, 22, 27, 10, 29, 26, 18, 16, 28, 18, 26, 37, 36, 25, 28, 36, 28, 31, 22, 20, 15, 13, 15, 18, 12, 15, 21, 21, 12, 18, 17, 12, 11, 18, 16, 14, 21, 20, 18, 19, 15, 20, 22, 16, 22, 15, 23, 26, 16, 8, 13, 19, 30, 16, 15, 11, 22, 12, 14, 8, 10, 14, 13, 8, 12, 22, 11, 13, 18, 16, 21, 21, 14, 14, 11, 14, 15, 9, 23, 19, 15, 17, 9, 10, 11, 12, 14, 16, 9, 17, 15, 20, 14, 18, 18, 32, 34, 55, 54, 51, 72, 78, 83, 99, 118, 171, 138, 177, 191, 158, 159, 123, 106, 136, 121, 121, 148, 137, 118, 145, 150, 150, 133, 98, 111, 118, 111, 104, 129, 124, 104, 144, 126, 118, 133, 124, 108, 87, 87, 83, 85, 75, 76, 75, 62, 84, 46, 61, 54, 54, 63, 45, 54, 66, 46, 52, 51, 49, 51, 52, 62, 50, 67, 72, 53, 53, 83, 54, 39, 57, 31, 53, 31, 38, 38, 42, 31, 29, 38, 39, 39, 26, 43, 36, 45, 68, 57, 60, 42, 39, 41, 38, 46, 44, 40, 47, 57, 45, 59, 53, 59, 81, 78, 75, 95, 46, 62, 1, 0, 0]
小結:以上介紹了Image模組最基本的功能,作為對PIL庫初步的認識已經足夠了,值得說明的是,這裡提到只是Image一部分功能而已,要對整個Image模組的功能有一個全面的瞭解和掌握,請參見PIL-handbook.pdf。
4.ImageDraw模組:
ImageDraw模組提供了基本的圖形能力,這裡的圖形能力指的主要是圖形的繪製能力。PIL庫提供了比較豐富的圖形繪製函數,可以繪製直線、弧線、矩形、多邊形、橢圓、扇形等等。ImageDraw實現了一個Draw類,所有的圖形繪製功能都是在Draw類執行個體的方法中實現的。執行個體化一個Draw類執行個體很簡單:
import Image,ImageDraw
img = Image.open("img.jpg")
draw = ImageDraw.Draw(img)
首先要匯入ImageDraw模組。然後,因為繪圖操作是在映像上進行的,因此執行個體化Draw類的時候要把Image對象img通過參數傳遞給Draw類的建構函式。現在,你就可以調用draw的各種方法在img上繪製圖形了。
(1)繪製直線:
import Image,ImageDraw
img = Image.open("img.jpg")
draw = ImageDraw.Draw(img)
width,height = img.size
draw.line(((0,0),(width-1,height-1)),fill=255)
draw.line(((0,height-1),(width-1,0)),fill=255)
img.save("cross_line.jpg")
解釋一下上面這段代碼:
前面三行這裡就不解釋了。width,height = img.size是得到img的大小,得到這兩個屬性的主要目的是要在下面的兩行代碼中使用:
draw.line(((0,0),(width-1,height-1)),fill=255)
draw.line(((0,height-1),(width-1,0)),fill=255)
這兩行代碼在img映像的兩個對角線方向繪製了兩條直線。最後,我們把繪製了兩條對角線的映像儲存為cross_line.jpg,最後得到的效果如下面所示:
(2)繪製圓:
import Image,ImageDraw
img = Image.open("img.jpg")
width,height = img.size
draw = ImageDraw.Draw(img)
draw.arc((0,0,width-1,height-1),0,360,fill=255)
img.save("circle.jpg")
這幾行代碼和上面繪製對角線的代碼相比,只更改了一行,即:
draw.arc((0,0,width-1,height-1),0,360,fill=255)
說明:
(0,0,width-1,height-1)指定了所畫弧線的界限;
0,360是所畫弧線的起始角度和終止角度;
fill=255指定了所畫線的顏色,注意:PIL的文檔上說這裡應該用outline=255,但是我發現實際只能用fill=255來指定弧線的顏色。
繪製圓後的映像:
小結:有關圖形繪製的操作都是類似的,因此這裡只給出一個簡略的介紹。詳細規範請參見PIL-handbook.pdf。
5.ImageEnhance模組:
這個模組提供了一個常用的映像增強工具箱。可以用來進行色彩增強、亮度增強、對比增強、映像尖銳利化等等增強操作。所有操作都有相同形式的介面——通過相應類的enhance方法實現:色彩增強通過Color類的enhance方法實現;亮度增強通過Brightness類的enhance方法實現;對比增強通過Contrast類的enhance方法實現;尖銳利化通過Sharpness類的enhance方法實現。所有的操作都需要向類的建構函式傳遞一個Image對象作為參數,這個參數定義了增強作用的對象。同時所有的操作都返回一個新的Image對象。如果傳給enhance方法的參數是1.0,則不對原映像做任何改變,直接返回原映像的一個拷貝。下面我們通過幾個簡單的例子進行說明:
(1)亮度增強:
import Image,ImageEnhance
img = Image.open("img.jpg")
brightness = ImageEnhance.Brightness(img)
bright_img = brightness.enhance(2.0)
bright_img.save("bright.jpg")
說明:
brightness = ImageEnhance.Brightness(img)
這一行把img傳給Brightness類,得到一個Brightness類執行個體;
bright_img = brightness.enhance(2.0)
這一行調用brightness執行個體的enhance方法,傳入的參數指定將亮度增強2倍;
我們最後得到bright.jpg映像看起來像這樣:
右邊的的映像是增強之前的映像(原映像),注意兩者的亮度差比是很大的。
(2)映像尖銳利化:
import Image,ImageEnhance
img = Image.open("img.jpg")
sharpness = ImageEnhance.Sharpness(img)
sharp_img = sharpness.enhance(7.0)
sharp_img.save("bright.jpg")
這段代碼和上面的完全類似,因此這裡不做過多的說明。我們來看一下增強前後的效果對比:
右邊的的映像是增強之前的原映像,注意兩者的尖銳利化程度是很不一樣的。
(3)對比增強:
import Image,ImageEnhance
img = Image.open("img.jpg")
contrast = ImageEnhance.Contrast(img)
contrast_img = contrast.enhance(2.0)
contrast_img.save("contrast.jpg")
同上,我們只看增強前後的效果對比:
很明顯,增強之後的映像(左邊)比原來的映像(右邊)對比提高了。
小結:用ImageEnhance來進行常用的映像增強是有效,並且很簡單。當然,對於精細複雜的映像增強操作而言這裡提供的功能不夠強大,但是在進行簡單的映像增強操作的時候,一種簡單易行的解決方案無疑是很迷人的。
6.總結:
在批處理或者簡單的影像處理任務中,採用python和PIL(Python Image Library)的組合來完成影像處理任務是一個很不錯的選擇。設想有一個需要對某個檔案夾下的所有映像將對比提高2倍的任務。用python來做將是十分簡單的。當然,我也不得不承認python在影像處理方面的功能還比較弱,顯然還不適合用來進行濾波、特徵提取等等一些更為複雜的應用。我個人的觀點是,當你要實現這些“進階”的演算法的時候,好吧,把它交給MATLAB去完成。但是,如果你面對的只是一個通常的不要求很複雜演算法的影像處理任務,那麼,python應該才是你的最佳搭檔。
參考文獻:
1.《數位影像處理》(第二版);岡薩雷斯;電子工業出版社;2003;
2.《Python Image Library Handbook》;Fredrik Lundh,Matthew Ellis;PythonWare.Inc;2002;
3.《Python Documentation》(Release 2.3.3);Guido van Rossum;2003;
4.www.python.org
5.www.pythonware.org